The 12d Model Programming Language
A C++-based macro language for civil and survey engineering. Browse the complete library reference, type system, and code snippets pulled directly from the official manual and the open-source language server.
Where to start
Quick Start
Install VS Code and the 12dPL extension to get full language support.
Variable Types
Mathematical, geometric, database and interface types.
Flow Control
if/else, switch, while, for, do-while, break, continue, goto.
Functions
User-defined functions, overloading, recursion and scoping rules.
Library Reference
3,000+ built-in functions covering every part of the 12d Model API.
Type Reference
Complete catalogue of every type the language exposes, with descriptions.
Snippets
Ready-to-paste code patterns for panels, loops, functions and more.
Examples
Complete, working macro programs to learn from.
What is 12dPL?
The 12d Model Programming Language (12dPL), also known as the 12d Model Macro Language or 4DML, is a powerful programming language that runs from within 12d Model โ a leading civil and survey engineering software platform.
12dPL is based on a subset of C++ with special extensions to allow easy manipulation of 12d Model data. A large number of intrinsic functions are supplied which cover most aspects of civil modelling. Programs written in 12dPL are often called macros, but they are fully fledged computer programs.
Hello World
// My first 12dPL program
void main()
{
Print("Hello, 12d World!\n");
}
Key Features
- C++-style syntax โ familiar to C, C++, and Java developers
- Strong type system with automatic promotions between numeric types
- Rich set of geometric types:
Point,Line,Arc,Spiral,Segment - Direct access to 12d Model database via handles (
Element,Model,View) - GUI panel creation with
Panel,Widget, and dozens of input controls - File I/O, XML, and ODBC database access
- Function overloading and recursion
- Over 1,000 built-in library functions
Install VS Code & the 12dPL Extension
The recommended way to write 12dPL is in Visual Studio Code with the 12dPL Language extension installed. You get syntax highlighting, autocompletion for 3000+ library calls, hover documentation, go-to-definition, and inline diagnostics.
Step 1 โ Install VS Code
Download and install VS Code from the official site:
Pick the installer for your platform (Windows / macOS / Linux) and run it with the default options.
Step 2 โ Install the 12dPL Language extension
Inside VS Code:
- Open the Extensions view โ
Ctrl+Shift+Xon Windows/Linux,Cmd+Shift+Xon macOS. - Search for 12dPL Language (publisher:
nightworks). - Click Install.
Or install it from the command line:
code --install-extension nightworks.12dpl-lang-server
Marketplace link: 12dPL Language on the VS Code Marketplace.
Step 3 โ Open a 12dPL file
Open any .4dm or .4do file in VS Code. The extension activates automatically, and you'll get colorisation, completions, and diagnostics from that point on.
cc4d.exe compiler itself only ships with 12d Model on Windows, so compiling and running macros (next page) is Windows-only โ but you can author and lint 12dPL anywhere.
Compiling & Running a 12dPL Program
A 12dPL program consists of one file containing a starting function called main, and zero or more user-defined functions. The filename must end in .4dm.
Step 1 โ Write your macro
Create a file called mymacro.4dm:
void main()
{
Print("Macro running!\n");
}
Step 2 โ Compile
You can compile in three ways:
A. From inside 12d Model
Utilities => Macros => Compile
Utilities => Macros => Compile/run
B. Drag-and-drop
Drop a .4dm file onto an open 12d Model window. The Compile/Run a Macro panel appears automatically.
C. Command line (outside 12d Model)
"C:\Program Files\12d\12dmodel\15.00\nt.x64\cc4d.exe" mymacro.4dm
# With error log:
"C:\Program Files\12d\12dmodel\15.00\nt.x64\cc4d.exe" -log mymacro.4dl mymacro.4dm
The compiler checks syntax and, if there are no errors, creates mymacro.4do โ the compiled object ready to run.
Step 3 โ Run
To run a compiled .4do file from within 12d Model:
Utilities => Macros => Run
Select the .4do file from the list, optionally add command-line arguments, and click Run.
Alternatively, drag-and-drop a .4do file onto 12d Model to run it directly.
Mouse Conventions
In this documentation, mouse buttons are referred to as:
| Symbol | Meaning |
|---|---|
LB | Left button โ press and release |
MB | Middle button / scroll wheel โ press and release |
RB | Right button โ press and release |
Basic Language Structure
A 12dPL program is a text file (ending in .4dm) that contains a mandatory main function and zero or more user-defined functions. The language is case-sensitive.
Topics in this section:
Names & Reserved Words
Names
A name denotes an object, function, enumerator, type, or value. Rules:
- Must start with an alphabetic character (
aโz,AโZ) - Can contain letters, digits (
0โ9), and underscores (_) - No length restriction
- Case-sensitive โ
MyVarandmyvarare different - Must be declared before use
Reserved Keywords
The following names cannot be used for user-defined variables or functions:
Built-in Types
IntegerInteger64RealTextUidGuid
ElementModelViewTinPointLine
ArcSpiralParabolaSegmentCurveMenu
PanelWidgetFunctionMacro_FunctionUndoUndo_List
AttributesAttribute_BlobBlobScreen_TextTextstyle_DataEquality_Label
Vector2Vector3Vector4Matrix3Matrix4Colour
TimeFileMap_FileXML_DocumentXML_Node
Dynamic_IntegerDynamic_Integer64Dynamic_RealDynamic_TextDynamic_Element
C++ Control Keywords
breakcasecontinuedefaultdoelse
forgotoifreturnswitchvoid
whilesizeofstaticstructtypedef
Container Type Keywords
Container keywords follow the pattern $KeyType_$KeyType_Map, $KeyType_Set, etc., where $KeyType is one of: Integer, Integer64, Real, Text, Uid, Guid, Point, Vector2, Vector3, Vector4.
Examples: Real_Set, Text_Multiset, Integer_Text_Multimap
Preprocessing (#include)
You can include other files using the #include directive:
#include "filename"
Example
// file: helpers.h
Point Coord(Real x, Real y, Real z)
{
Point p;
Set_x(p, x);
Set_y(p, y);
Set_z(p, z);
return(p);
}
// file: mymacro.4dm
#include "helpers.h"
void main()
{
Point p = Coord(10.0, 20.0, 2.34);
}
set_ups.h is commonly included in macros. It provides useful constants such as TRUE, FALSE, CHECK_MODEL_EXISTS, SELECT_STRING, and many more.
#include "set_ups.h"
void main()
{
// set_ups.h constants now available
}
Variables & Types
Variables must be declared before use. A declaration consists of a type followed by a comma-separated list of names ending with a semicolon.
Integer fred, joe, tom;
Real x = 1.0, y = 2.0;
Text message = "Hello";
12dPL has a rich type system organised into these categories:
| Category | Examples | Persistent? |
|---|---|---|
| Mathematical | Integer, Real, Text, Vector3 | No โ program only |
| Geometric Construction | Point, Line, Arc, Spiral | No โ program only |
| 12d Database Handles | Element, Model, View, Tin | Yes โ stored in project |
| 12d Internal | Uid, Attributes, Textstyle_Data | Via handles |
| Interface | Panel, Widget, Button, Model_Box | No โ program only |
| File | File, XML_Document, Map_File | Via file system |
| ODBC | Connection, Select_Query | Via database |
| Arrays | Real[100], Dynamic_Element | No โ program only |
Mathematical Variable Types
Standard variables for arithmetic calculations. They exist only during macro execution.
| Type | Description | Example |
|---|---|---|
Integer | 32-bit signed whole number | -1, 0, 76875 |
Integer64 | 64-bit signed whole number | 123LL, -123456789123 |
Real | 64-bit IEEE floating point (~14 significant figures) | -1.0, 3.14, 1.0e+6 |
Text | A sequence of characters | "Hello" |
Vector2 | Two Reals (X, Y) | |
Vector3 | Three Reals (X, Y, Z) | |
Vector4 | Four Reals (X, Y, Z, W) | |
Matrix3 | 3ร3 matrix of Reals (9 values) | |
Matrix4 | 4ร4 matrix of Reals (16 values) |
Automatic Promotions
The following promotions happen automatically when matching function arguments or return types:
| From | To |
|---|---|
Integer | Real, Integer64 |
Integer64 | Real, Integer |
Real | Integer, Integer64 |
Vector2 | Vector3 |
Vector3 | Vector4, Vector2 |
Vector4 | Vector3 |
Integer < Integer64 < Real. Overflow is not auto-promoted โ 2048 * 2048 * 2048 overflows as Integer.
Geometric Construction Types
These are temporary in-memory objects used for geometric calculations. They are not stored in 12d Model models.
| Type | Description |
|---|---|
Point | 3D point with x, y, z coordinates |
Line | 3D line joining two Points |
Arc | A helix: projects onto a circle in the (x,y) plane, with linearly interpolated z. Not a circle in 3D space. |
Spiral | A mathematically-defined transition curve (clothoid or cubic parabola) with continuously varying radius |
Parabola | A vertical geometry parabola in the (chainage, height) plane |
Segment | A union type: can be a Point, Line, Arc, Parabola, or Spiral |
Point p;
Set_x(p, 100.0);
Set_y(p, 200.0);
Set_z(p, 10.5);
Database Handles
Unlike construction entities, these variables act as handles to data stored in the 12d Model project database. The data persists after the macro terminates.
| Type | Description |
|---|---|
Element | Handle to a 12d Model string/element (Super, Arc, Circle, Drainage, Tin, etc.) |
Tin | Handle to a triangulated irregular network |
Model | Handle to a 12d Model model (layer/group of elements) |
View | Handle to a 12d Model view |
Macro_Function / Function | Handle to a 12d Model user-defined function |
Undo_List | A list for combining undo operations |
Element Types
The type of an Element is returned by Get_type(Element elt, Text &type):
| Element Type | Description |
|---|---|
Super | General string with at least (x,y,z,radius) at each vertex โ preferred type |
Super Alignment | String with full horizontal geometry via intersection point methods |
Arc | Arc in (x,y) plane with linear z interpolation |
Circle | Circle in (x,y) plane with constant z |
Text | String with text at a vertex |
Tin | Triangulated Irregular Network |
Drainage | Drainage/sewer element |
Pipeline | Alignment string with diameter |
Plot Frame | Element for plan plot production |
Element elt;
Text elt_type;
Get_type(elt, elt_type);
if (elt_type == "Super") {
Print("It's a Super string!\n");
}
12d Internal Variable Types
These types help access and manage data stored via database handles.
| Type | Description |
|---|---|
Uid | Unique identifier for entities in the 12d Model database |
Guid | Global unique identifier for a 12d Model project |
Attributes | Handle to a user-defined attribute structure (attachable to Projects, Models, Elements) |
SDR_Attribute | Special attributes for the 12d Survey Data Reduction process |
Blob | Binary data object |
Attribute_Blob | Binary attribute object |
Screen_Text | Text displayed on screen |
Textstyle_Data | Holds text formatting: colour, textstyle, justification, height |
Equality_Label | Holds information for labelling text as an equality |
Undo | Holds information placed on the 12d Model undo system |
Interface Variable Types
These types are used to build interactive GUI panels and communicate with macro users. All are derived from Widget.
Core Layout Types
| Type | Description |
|---|---|
Panel | Top-level window container for a macro's GUI |
Widget | Base type for all UI controls |
Vertical_Group | Stacks widgets vertically |
Horizontal_Group | Arranges widgets horizontally |
Widget_Pages | Multi-page panel tabs |
Menu | User-defined 12d Model menu |
Input Controls
ButtonSelect_ButtonAngle_BoxAttributes_Box
Chainage_BoxChoice_BoxColour_BoxDate_Time_Box
Directory_BoxDraw_BoxFile_BoxFunction_Box
Graph_BoxGridCtrl_BoxHyperLink_BoxInput_Box
Integer_BoxJustify_BoxLinestyle_BoxList_Box
Message_BoxColour_Message_BoxModel_BoxName_Box
New_Select_BoxNew_XYZ_BoxReal_BoxReport_Box
Select_BoxSymbol_BoxTab_BoxTarget_Box
Text_Edit_BoxText_Style_BoxTick_BoxNamed_Tick_Box
Tin_BoxView_BoxXYZ_BoxTree_Box
File Interface Variable Types
| Type | Description |
|---|---|
File | A standard file unit for reading/writing files |
Map_File | A file for mapping element properties |
Plot_Parameter_File | A file for plot parameters |
XML_Document | File contents structured as an XML document |
XML_Node | A node within an XML document |
ODBC Database Variable Types
These types provide access to external ODBC databases from within a macro.
| Type | Description |
|---|---|
Connection | Connection to an ODBC data source |
Select_Query | Retrieve data from the database |
Insert_Query | Add data to the database |
Update_Query | Update data in the database |
Delete_Query | Delete data from the database |
Database_Result | Holds the result set from a query |
Transaction | Database transaction management |
Parameter_Collection | Query parameters |
Query_Condition | Conditions for a query |
Manual_Condition | Manually specified conditions |
Arrays
12dPL supports two kinds of arrays: fixed-size and dynamic.
Fixed Arrays
Size is specified at declaration (can be a literal or a previously-assigned variable). Size is fixed after declaration.
Real real_array[100]; // 100 Reals, indexed 1..100
Integer N = 50;
Text text_array[N]; // 50 Texts (size fixed at this line)
real_array[10] = 3.14; // access item 10
Dynamic Arrays
Dynamic arrays can grow or shrink at runtime. Items are accessed through function calls, not subscript notation.
| Type | Description |
|---|---|
Dynamic_Element | Variable-length array of Elements |
Dynamic_Integer | Variable-length array of Integers |
Dynamic_Integer64 | Variable-length array of 64-bit Integers |
Dynamic_Real | Variable-length array of Reals |
Dynamic_Text | Variable-length array of Text values |
Dynamic_Element elts;
Integer num_elts;
Get_elements(model, elts, num_elts);
for (Integer i = 1; i <= num_elts; i++) {
Element e;
Get_item(elts, i, e);
// process element e
}
Constants (Literals)
Integer Constants
Any sequence of decimal digits. Constants โฅ 2ยณยน are automatically treated as 64-bit integers. Append LL to force 64-bit.
Integer a = 1;
Integer b = 76875;
Integer64 big = 123LL;
Integer64 huge = -123456789123; // auto 64-bit
Real Constants
Must include a decimal point. Optional fractional part and optional exponent (e or E).
Real x = 6.;
Real y = 1.0;
Real z = 1.0e+1; // 10.0
Real w = .1e+2; // 10.0
// Note: 1e1 is NOT valid โ decimal point is mandatory
Text Constants
A sequence of characters enclosed in double quotes. Supports escape sequences:
Text s1 = "Hello, world!";
Text s2 = "She said \"hello\""; // embedded double quote
Text s3 = "Line1\nLine2"; // newline
Text s4 = "back\\slash"; // backslash
| Escape | Meaning |
|---|---|
\n | Newline |
\" | Double quote |
\\ | Backslash |
Operators
Arithmetic Operators
| Operator | Meaning | Notes |
|---|---|---|
+ | Addition | |
- | Subtraction | |
* | Multiplication | Also dot product for vectors, matrix multiply |
/ | Division | Integer division truncates the fractional part |
% | Modulus | Integer remainder: 7 % 3 == 1 |
^ | Cross product | For Vector2 and Vector3 only |
Relational Operators
| Operator | Meaning |
|---|---|
== | Equal to |
!= | Not equal to |
< | Less than |
<= | Less than or equal to |
> | Greater than |
>= | Greater than or equal to |
Logical Operators
| Operator | Meaning |
|---|---|
&& | Logical AND |
|| | Logical OR |
! | Logical NOT |
Increment / Decrement
i++; // post-increment: i = i + 1
i--; // post-decrement: i = i - 1
++i; // pre-increment
--i; // pre-decrement
Bitwise Operators
| Operator | Meaning |
|---|---|
& | Bitwise AND |
| | Bitwise inclusive OR |
^ | Bitwise exclusive OR (XOR) |
~ | One's complement (unary) |
Assignment Operators
x = y; // assignment
x += 2; // x = x + 2
x -= 2; // x = x - 2
x *= 2; // x = x * 2
x /= 2; // x = x / 2
x %= 2; // x = x % 2
Operator Precedence (high โ low)
| Operators | Associativity |
|---|---|
() [] | Left to right |
! ~ ++ -- + - * & (unary) | Right to left |
* / % | Left to right |
+ - | Left to right |
< <= > >= | Left to right |
== != | Left to right |
& | Left to right |
^ | Left to right |
| | Left to right |
&& | Left to right |
|| | Left to right |
? : | Right to left |
= += -= *= /= %= | Right to left |
Flow Control
12dPL supports the standard C++ flow control statements. In a program, a logical expression evaluates to true if its value is non-zero, false if zero.
if / else / else if
if
if (x == 5) {
x = x + 1;
y = x * y;
}
if / else
if (x > 0) {
Print("positive\n");
} else {
Print("non-positive\n");
}
else if
if (x > 0) {
Print("positive\n");
} else if (x < 0) {
Print("negative\n");
} else {
Print("zero\n");
}
Conditional Expression (Ternary)
The ? : operator provides a concise inline if-else:
// y = absolute value of x
Real y = (x >= 0) ? x : -x;
switch
Evaluates an expression and jumps to the matching case. Supports Integer, Integer64, Real, and Text expressions.
case label must be enclosed in curly braces {}.
switch (a) {
case 1 : {
x = y;
break;
}
case 2: {
x = y + 1;
z = x * y;
// no break โ falls through to case 3
}
case 3: case 4: {
x = z + 1;
break;
}
default : {
y = z + 2;
break;
}
}
switch with Text
Text cmd = "write";
switch (cmd) {
case "write": {
Print("Writing...\n");
break;
}
case "read": {
Print("Reading...\n");
break;
}
default: {
Print("Unknown command\n");
break;
}
}
Loops
while
Integer x = 10;
Real product = 1.0;
while (x > 0) {
product = product * x;
x = x - 1;
}
for
// Sum numbers 1..10
Integer j = 0;
for (Integer i = 1; i <= 10; i++) {
j = j + i;
}
Any part of the for header can be omitted (the semicolons must remain). If the test is omitted it is taken as permanently true.
do while
Integer i = 1;
do {
x = x + i;
i++;
} while (i < 10);
break
Exits the innermost for, while, do while, or switch:
for (Integer i = 1; i <= 100; i++) {
if (i == 50) break; // stop at 50
}
continue
Skips to the next iteration of the innermost loop:
for (Integer i = 1; i <= 10; i++) {
if (i % 2 == 0) continue; // skip even numbers
Print(To_text(i) + "\n");
}
goto and Labels
A label is a name followed by a colon and can be attached to any statement in a function. goto transfers control to the labelled statement.
for (Integer i = 1; i <= 10; i++) {
if (some_error_condition) goto error;
}
Print("Success\n");
return;
error:
Print("An error occurred\n");
goto cannot jump over variable declarations at the same nesting level. Use extra braces {} to increase nesting if needed.
Functions
Functions break tasks into reusable units. Communication is via arguments, return values, and global variables.
- main() โ entry point
- User-Defined Functions
- Function Prototypes
- Pass by Value / Reference
- Overloading
- Recursion
- Blocks & Scopes
All 12dPL supplied functions start with a capital letter. Function names are case-sensitive.
main() Function
Every 12dPL program must have exactly one main function. It is the entry point when a macro is run.
void main()
{
// your program code here
}
main is a void function โ it returns nothing. It terminates when:
- The last line of code is executed, or
- A
return;statement is encountered
User-Defined Functions
User-defined functions must be defined before their first call in the file (or declared via a prototype โ see below).
// Function definition โ must come before main() or have a prototype
Integer add_values(Integer a, Integer b)
{
return(a + b);
}
void main()
{
Integer result = add_values(10, 20);
Print(To_text(result) + "\n"); // prints 30
}
Return Statement
Non-void functions must have a return as their last statement. Void functions use return; (or just fall off the end).
Integer user_function(Integer fred, Real joe, Element tom)
{
// ... code ...
return(0); // must be last statement in non-void function
}
Function Prototypes
A prototype declares a function's signature so it can be called before its definition appears in the file.
// Prototype (note the semicolon and no body)
Integer user_function(Integer fred, Real joe, Element tom);
// or omitting parameter names:
Integer user_function(Integer, Real, Element);
void main()
{
Integer r = user_function(1, 2.0, elt); // OK โ prototype exists
}
// Actual definition can appear after main
Integer user_function(Integer fred, Real joe, Element tom)
{
// ...
return(0);
}
main function and built-in library functions never need to be prototyped.
Passing by Value / Reference
By Value (default)
A copy of the argument is passed. Changes inside the function do not affect the caller.
void bad_square(Integer x)
{
x = x * x; // only modifies the local copy
}
void main()
{
Integer x = 10;
bad_square(x);
// x is still 10
}
By Reference (&)
Place & after the type to pass by reference. Changes inside the function affect the original variable. Used whenever a function needs to return values through its arguments.
void square(Integer &x)
{
x = x * x; // modifies the caller's variable
}
void main()
{
Integer x = 10;
square(x);
// x is now 100
}
// Real-world example: Get_name returns the name via a reference argument
Text name;
Get_name(element, name); // name is filled in by Get_name
Print(name + "\n");
Function Overloading
Multiple functions can share the same name if they differ in argument count or types. 12dPL selects the correct version automatically.
void swap(Integer &x, Integer &y) { Integer z = x; x = y; y = z; }
void swap(Real &x, Real &y) { Real z = x; x = y; y = z; }
void swap(Text &x, Text &y) { Text z = x; x = y; y = z; }
void main()
{
Integer ix = 1, iy = 2;
Real rx = 1.0, ry = 2.0;
Text tx = "a", ty = "b";
swap(ix, iy); // calls Integer version
swap(rx, ry); // calls Real version
swap(tx, ty); // calls Text version
}
Recursion
12dPL supports recursive functions.
// Fibonacci sequence
Integer fib(Integer n)
{
return n < 2 ? 1 : fib(n - 1) + fib(n - 2);
}
void main()
{
for (Integer i = 0; i <= 10; i++) {
Print(To_text(fib(i)) + "\n");
}
}
Blocks & Scopes
A block is code enclosed in {}. Blocks can be nested. Three scope levels exist:
| Scope | Description |
|---|---|
| Local | Declared in a block โ accessible in that block and any nested blocks after the declaration |
| Function | Labels only โ accessible anywhere in the enclosing function |
| Global | Declared outside all functions in an enclosing {} โ accessible from that point onwards in the file |
// Global variables โ must be wrapped in braces
{
Integer global_count;
Real global_total;
}
void main()
{
Integer a = 1; // local to main
{
Integer x = 10; // local to this inner block
global_count = x; // OK โ global_count is visible here
}
// x is NOT accessible here
{
Real x = 10.0; // different x โ local to this block
global_total = x;
}
}
Library Overview
12dPL provides over 1,000 built-in functions organized into categories. All library functions start with a capital letter. Most return 0 on success and non-zero on failure.
Function Return Codes
The general convention is:
0โ success- Non-zero โ error or special condition
Library Categories
| Category | Description |
|---|---|
| Text | String manipulation, conversion, formatting |
| Maths | Trigonometry, logarithms, rounding, etc. |
| Input / Output | Console output, file reading/writing, clipboard |
| System | Date/time, process management, system queries |
| Dynamic Arrays | Add, get, set, clear dynamic arrays |
| Points & Geometry | Points, lines, arcs, spirals, segments |
| Segment Geometry | Length, area, distance, offset, intersection |
| Vectors & Matrices | Dot product, cross product, transforms |
| Colours | Colour creation and manipulation |
| Project | Project access and properties |
| Models | Create, delete, navigate models |
| Views | Create, navigate views |
| Elements | Create, modify, query all element types |
| Super Strings | Full set of Super string manipulation functions |
| Tin | TIN creation, triangulation, queries |
| Panels & Widgets | Create interactive GUI panels |
| XML | Parse and generate XML |
| ODBC | External database connectivity |
| Attributes | User-defined attributes on elements |
| Undos | Register undo operations |
Text Functions
Commonly Used Functions
| Function | Description |
|---|---|
To_text(value) | Convert Integer, Real, Uid, etc. to Text |
To_integer(text, &i) | Parse Text as Integer |
To_real(text, &r) | Parse Text as Real |
Text_length(text) | Number of characters in the text |
Text_upper(text) | Convert to upper case |
Text_lower(text) | Convert to lower case |
Text_trim(text) | Remove leading and trailing whitespace |
Text_substr(text, start, len) | Extract a substring |
Text_pos(text, pattern) | Find position of pattern in text |
String Concatenation
Text a = "Hello";
Text b = " World";
Text c = a + b; // "Hello World"
Text msg = "Count: " + To_text(42); // "Count: 42"
Example
void main()
{
Text name;
Get_name(element, name);
Integer n = Text_length(name);
Print("Name: " + name + " (" + To_text(n) + " chars)\n");
}
Math Functions
| Function | Description |
|---|---|
Abs(x) | Absolute value |
Sqrt(x) | Square root |
Sin(angle) | Sine (radians) |
Cos(angle) | Cosine (radians) |
Tan(angle) | Tangent (radians) |
Atan2(y, x) | Arc tangent of y/x in radians |
Log(x) | Natural logarithm |
Log10(x) | Base-10 logarithm |
Exp(x) | e raised to the power x |
Pow(x, y) | x raised to the power y |
Floor(x) | Round down to nearest integer |
Ceil(x) | Round up to nearest integer |
Round(x) | Round to nearest integer |
Max(a, b) | Larger of two values |
Min(a, b) | Smaller of two values |
Pi() | Returns ฯ (3.14159โฆ) |
Real pi = Pi();
Real angle_rad = 45.0 * pi / 180.0;
Real s = Sin(angle_rad);
Real c = Cos(angle_rad);
Print("sin(45ยฐ) = " + To_text(s) + "\n");
Input / Output
Console Output
Print("Hello\n"); // write to output window
Print("Value = " + To_text(42) + "\n");
Clear_console(); // clear the output window
File Operations
File f;
File_open("output.txt", "w", "ccs=UNICODE", f);
File_write_line(f, "First line");
File_write_line(f, "Second line: " + To_text(value));
File_flush(f);
File_close(f);
File Prompt
Text file_name;
File_prompt("Select output file", "*.txt", file_name);
File f;
File_open(file_name, "w", "ccs=UNICODE", f);
Message Prompts
// Show a message dialog
Error_prompt("Something went wrong!");
// Prompt for a yes/no answer
Integer answer = Yes_no_prompt("Continue?");
Elements & Models
Getting Element Information
Element elt;
Text name, type;
Integer colour, num_verts;
Model model;
Get_name(elt, name); // get element name
Get_type(elt, type); // get element type string ("Super", "Tin", etc.)
Get_colour(elt, colour); // get colour index
Get_points(elt, num_verts); // get number of vertices
Get_model(elt, model); // get the model containing this element
Modifying Elements
Set_name(elt, "New Name");
Set_colour(elt, 3);
Element_draw(elt); // redraw the element on screen immediately
Iterating Elements in a Model
Model model = Get_model("My Model");
Dynamic_Element elts;
Integer num_elts;
Get_elements(model, elts, num_elts);
for (Integer i = 1; i <= num_elts; i++) {
Element e;
Get_item(elts, i, e);
Text name;
Get_name(e, name);
Print(name + "\n");
}
Super String Vertex Coordinates
Element super_str;
Integer n;
Get_points(super_str, n);
for (Integer i = 1; i <= n; i++) {
Real x, y, z;
Get_super_vertex_coord(super_str, i, x, y, z);
Print(" [" + To_text(i) + "] x=" + To_text(x)
+ " y=" + To_text(y) + " z=" + To_text(z) + "\n");
}
Panels & Widgets
12dPL provides a complete GUI framework for building interactive macro dialogs.
Basic Panel Pattern
#include "set_ups.h"
void main()
{
// 1. Create the panel and widgets
Panel panel = Create_panel("My Panel Title");
Message_Box msg = Create_message_box("Ready");
Input_Box input = Create_input_box("Name", msg);
Button ok_btn = Create_finish_button("OK", "ok_reply");
// 2. Layout with groups
Vertical_Group vg = Create_vertical_group(0);
Append(input, vg);
Append(msg, vg);
Horizontal_Group hg = Create_button_group();
Append(ok_btn, hg);
Append(hg, vg);
Append(vg, panel);
// 3. Show the panel
Show_widget(panel);
// 4. Event loop
Integer running = 1;
while (running) {
Integer id; Text cmd, msg_text;
Wait_on_widgets(id, cmd, msg_text);
switch (id) {
case Get_id(panel): {
if (cmd == "Panel Quit") running = 0;
break;
}
case Get_id(ok_btn): {
if (cmd == "ok_reply") running = 0;
break;
}
}
}
}
Key Panel Functions
| Function | Description |
|---|---|
Create_panel(title) | Create a new panel |
Show_widget(panel) | Display the panel on screen |
Wait_on_widgets(id, cmd, msg) | Block until a widget event occurs |
Get_id(widget) | Get a widget's unique integer ID |
Set_data(widget, text) | Update a widget's display text |
Validate(widget, result) | Validate and retrieve a widget's value |
Append(child, parent) | Add a widget to a group or panel |
Set_optional(widget, 1) | Mark a widget as optional (greyed title) |
Common Widget Creators
Model_Box mb = Create_model_box("Model", msg, CHECK_MODEL_EXISTS);
File_Box fb = Create_file_box("File", msg, CHECK_FILE_NEW, "*.txt");
Real_Box rb = Create_real_box("Value", msg, 0.0);
Tick_Box tb = Create_tick_box("Enabled", msg);
Choice_Box cb = Create_choice_box("Option", msg, "A|B|C");
Colour_Box colb = Create_colour_box("Colour", msg);
Name_Box nb = Create_name_box("Name", msg);
Dynamic Arrays
Dynamic arrays grow at runtime and are accessed through function calls (not subscript notation). Indices start at 1.
Dynamic_Text Example
Dynamic_Text items;
Integer count = 0;
// Add items
Add_item(items, count, "Apple");
Add_item(items, count, "Banana");
Add_item(items, count, "Cherry");
// Iterate
for (Integer i = 1; i <= count; i++) {
Text item;
Get_item(items, i, item);
Print(item + "\n");
}
Key Dynamic Array Functions
| Function | Description |
|---|---|
Add_item(array, &count, value) | Append an item; count is incremented |
Get_item(array, index, &value) | Retrieve item at index (1-based) |
Set_item(array, index, value) | Set item at index |
Delete_item(array, index, &count) | Remove item at index |
Clear_items(array, &count) | Remove all items |
Get_count(array, &count) | Get number of items |
Library Reference
Every built-in 12dPL function with its signature, parameters and description. Data is sourced from the 12dpl-lang-server dev branch, which extracts the official PDF manual into a structured form.
Type Reference
The 12dPL type system covers primitive numbers, geometric primitives, database handles, file handles, UI widgets and dynamic containers. Descriptions below come from the language server’s typeDocumentation.json (extracted from the official manual).
Snippets Gallery
Ready-to-use code snippets for the most common 12dPL constructs. These mirror the snippets bundled with the VS Code language server, so trigger the matching prefix in your editor for the same expansion. Click Copy to grab a snippet straight into your clipboard.
Code Examples
Example 1 โ Hello World
void main()
{
Print("Hello, 12d World!\n");
}
Example 2 โ Write Model Elements to a File
// write_model.4dm
// Writes all element names in a model to a report file
Integer write_out_model(Model model, File file)
{
Text model_name;
Dynamic_Element model_elts;
Integer num_elts, ierr;
ierr = Get_name(model, model_name);
if (ierr != 0) return(ierr);
Uid model_uid;
Get_id(model, model_uid);
File_write_line(file, "Model uid " + To_text(model_uid));
Get_elements(model, model_elts, num_elts);
File_write_line(file, "There are " + To_text(num_elts)
+ " elements in: " + model_name);
for (Integer i = 1; i <= num_elts; i++) {
Element e;
Get_item(model_elts, i, e);
Text ename, etype;
Get_name(e, ename);
Get_type(e, etype);
Integer num_verts;
Get_points(e, num_verts);
File_write_line(file, ename + "\t" + etype
+ "\t" + To_text(num_verts) + " verts");
}
File_flush(file);
File_close(file);
return(0);
}
void main()
{
Text model_name;
Model model;
while (!Model_exists(model)) {
Model_prompt("Select a model", model_name);
model = Get_model(model_name);
}
Text file_name;
File_prompt("Enter file name", "*.rpt", file_name);
File f;
File_open(file_name, "w", "ccs=UNICODE", f);
write_out_model(model, f);
}
Example 3 โ Interactive Panel with String Selection
// string_info.4dm
// Panel to select a Super string and report its vertex count and dimensions
#include "set_ups.h"
void main()
{
Panel panel = Create_panel("String Info");
Message_Box msg = Create_message_box("");
New_Select_Box sel = Create_new_select_box("Select string",
"Pick a string", SELECT_STRING, msg);
Button finish = Create_finish_button("Finish", "finish_reply");
Vertical_Group vg = Create_vertical_group(0);
Append(sel, vg);
Append(msg, vg);
Horizontal_Group hg = Create_button_group();
Append(finish, hg);
Append(hg, vg);
Append(vg, panel);
Show_widget(panel);
Clear_console();
Integer running = 1;
while (running) {
Integer id; Text cmd, wmsg;
Wait_on_widgets(id, cmd, wmsg);
switch (id) {
case Get_id(panel): {
if (cmd == "Panel Quit") running = 0;
break;
}
case Get_id(finish): {
if (cmd == "finish_reply") running = 0;
break;
}
case Get_id(sel): {
if (cmd == "accept select") {
Element str; Integer ierr;
ierr = Validate(sel, str);
if (ierr != TRUE) {
Set_data(msg, "Invalid selection");
break;
}
Integer n;
Get_points(str, n);
Integer use2d, use3d;
Get_super_use_3d_level(str, use3d);
Get_super_use_2d_level(str, use2d);
Text info = To_text(n) + " vertices";
if (use3d == 1) info += " โ 3D (Att_ZCoord_Array)";
else if (use2d == 1) info += " โ 2D (Att_ZCoord_Value)";
else info += " โ no Z dimension";
Set_data(msg, info);
}
break;
}
}
}
}
Example 4 โ Recursive Fibonacci
Integer fib(Integer n)
{
return n < 2 ? 1 : fib(n - 1) + fib(n - 2);
}
void main()
{
for (Integer i = 0; i <= 10; i++) {
Print("fib(" + To_text(i) + ") = " + To_text(fib(i)) + "\n");
}
}
Example 5 โ Change String Name and Colour
// change_string.4dm โ optional Name and Colour boxes
#include "set_ups.h"
void main()
{
Panel panel = Create_panel("Change String Name & Colour");
Message_Box msg = Create_message_box("");
New_Select_Box sel = Create_new_select_box("Select string",
"Pick a string", SELECT_STRING, msg);
Name_Box nb = Create_name_box("New name", msg);
Colour_Box cb = Create_colour_box("New colour", msg);
Button finish = Create_finish_button("Finish", "finish_reply");
Set_optional(nb, 1); // name is optional
Set_optional(cb, 1); // colour is optional
Vertical_Group vg = Create_vertical_group(0);
Append(nb, vg);
Append(cb, vg);
Append(sel, vg);
Append(msg, vg);
Horizontal_Group hg = Create_button_group();
Append(finish, hg);
Append(hg, vg);
Append(vg, panel);
Show_widget(panel);
Integer running = 1;
while (running) {
Integer id; Text cmd, wmsg;
Wait_on_widgets(id, cmd, wmsg);
switch (id) {
case Get_id(panel): {
if (cmd == "Panel Quit") running = 0;
break;
}
case Get_id(finish): {
if (cmd == "finish_reply") running = 0;
break;
}
case Get_id(sel): {
if (cmd == "accept select") {
Element str; Integer ierr;
ierr = Validate(sel, str);
if (ierr != TRUE) { Set_data(msg, "Invalid"); break; }
Text new_name; Integer new_colour;
Integer vn = Validate(nb, new_name);
Integer vc = Validate(cb, new_colour);
if (vn == FALSE) { Set_data(msg, "Name error"); break; }
if (vc == FALSE) { Set_data(msg, "Colour error"); break; }
if (vn != NO_NAME) Set_name(str, new_name);
if (vc != NO_NAME) {
Set_colour(str, new_colour);
Element_draw(str);
}
Set_data(msg, "Changes applied");
}
break;
}
}
}
}
Type Quick Reference
All 12dPL Types at a Glance
| Type | Category | Description |
|---|---|---|
void | Special | Used only for functions that return no value |
Integer | Math | 32-bit signed integer |
Integer64 | Math | 64-bit signed integer |
Real | Math | 64-bit IEEE floating point |
Text | Math | String of characters |
Vector2 | Math | 2D vector (X,Y) |
Vector3 | Math | 3D vector (X,Y,Z) |
Vector4 | Math | 4D vector (X,Y,Z,W) |
Matrix3 | Math | 3ร3 matrix |
Matrix4 | Math | 4ร4 matrix |
Point | Geometric | 3D point (temporary) |
Line | Geometric | 3D line (temporary) |
Arc | Geometric | Helix / plan-circle (temporary) |
Spiral | Geometric | Transition curve (temporary) |
Parabola | Geometric | Vertical parabola (temporary) |
Segment | Geometric | Union of Point/Line/Arc/Parabola/Spiral |
Element | DB Handle | Handle to 12d Model string/element |
Tin | DB Handle | Handle to triangulated irregular network |
Model | DB Handle | Handle to a 12d Model model |
View | DB Handle | Handle to a 12d Model view |
Macro_Function | DB Handle | Handle to a 12d Model function |
Undo_List | DB Handle | List for combining undos |
Uid | Internal | Unique ID for a database entity |
Guid | Internal | Global unique ID for a project |
Attributes | Internal | User-defined attribute structure handle |
Textstyle_Data | Internal | Text colour/style/height data |
Panel | Interface | GUI panel container |
Widget | Interface | Base UI control type |
Button | Interface | Clickable button |
Message_Box | Interface | Read-only text display area |
Input_Box | Interface | Free-text input field |
File | File | File read/write handle |
XML_Document | File | XML document handle |
Connection | ODBC | External database connection |
Dynamic_Element | Array | Dynamic array of Elements |
Dynamic_Real | Array | Dynamic array of Reals |
Dynamic_Integer | Array | Dynamic array of Integers |
Dynamic_Text | Array | Dynamic array of Texts |
About & Legal Disclaimer
12dPL Docs is a community-maintained reference for the 12d Model Programming Language. It is built automatically from the open-source 12dpl-lang-server project so the function, type, and snippet listings stay in sync with the editor tooling.
What this site is
- A searchable, browsable view of the 3,000+ 12dPL library calls and ~360 built-in types.
- A reference for the snippets bundled with the VS Code extension.
- An overview of language structure, types, operators, flow control, and common examples.
What this site is not
This site is not official 12dPL documentation. It is a community-maintained reference and is not a replacement for the official 12d Model Programming Language manual or any documentation produced by 12d Solutions Pty Ltd.
Legal
- No affiliation. This project is independent and is not affiliated with, endorsed by, sponsored by, or in any way officially connected to 12d Solutions Pty Ltd or any of its subsidiaries. "12d", "12d Model", and related names are trademarks of their respective owners and are used here for descriptive purposes only.
- Source of content. Function signatures, type names, and descriptions are derived from publicly available references and the open-source 12dpl-lang-server project. Content may be incomplete, outdated, or contain errors.
- No warranty. All information is provided "as is", without warranty of any kind, express or implied, including but not limited to warranties of merchantability, fitness for a particular purpose, accuracy, or non-infringement.
- Limitation of liability. The maintainers and contributors of this site shall not be liable for any direct, indirect, incidental, special, consequential, or exemplary damages arising from the use of, or inability to use, this site or its content โ including but not limited to data loss, lost profits, or business interruption โ even if advised of the possibility of such damages.
- Use at your own risk. You are solely responsible for verifying any information from this site against the official 12d Model documentation before relying on it for production work, safety-critical work, contractual deliverables, or compliance purposes.
- Licensing. The website source is released under the MIT License. Trademarks, product names, and any third-party content remain the property of their respective owners.
- Reporting issues. If you believe content on this site is inaccurate or infringes on rights you hold, please open an issue on the project issue tracker and we will review it promptly.
For official, authoritative 12dPL documentation, please consult the manual provided by 12d Solutions.
© 12dpl-lang-server contributors. Site content released under MIT.
Comments & Whitespace
Whitespace
Spaces, tabs, newlines, and form feeds are all whitespace and are ignored except for separating tokens or inside quoted strings. Blank lines are ignored.
Comments
12dPL supports two comment styles identical to C++:
Example