12d Model v15.0

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.

3,126 Library calls
361 Built-in types
23 Code snippets
1,643 Manual pages

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.

Free Training Course: A free Self-Paced Online Training (SPOT) course is available from the Civil and Survey Institute. See civilandsurveying.com

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:

  1. Open the Extensions view โ€” Ctrl+Shift+X on Windows/Linux, Cmd+Shift+X on macOS.
  2. Search for 12dPL Language (publisher: nightworks).
  3. 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.

Tip: The extension works on all platforms. The 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.

Tip: Macros can also be bound to function keys, toolbars, and custom menu entries. See the 12d Model Reference Manual for details.

Mouse Conventions

In this documentation, mouse buttons are referred to as:

SymbolMeaning
LBLeft button โ€” press and release
MBMiddle button / scroll wheel โ€” press and release
RBRight 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 โ€” MyVar and myvar are 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

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++:

// Line comment โ€” everything from // to end of line is ignored

/* Block comment โ€” everything between /* and */ is ignored,
   and can span multiple lines */

Example

void main()
{
    Real y = 1; // the rest of this line is a comment

    /* this comment can carry
       over many lines until
       we reach the termination characters */
}

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);
}
Tip: The standard file 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:

CategoryExamplesPersistent?
MathematicalInteger, Real, Text, Vector3No โ€” program only
Geometric ConstructionPoint, Line, Arc, SpiralNo โ€” program only
12d Database HandlesElement, Model, View, TinYes โ€” stored in project
12d InternalUid, Attributes, Textstyle_DataVia handles
InterfacePanel, Widget, Button, Model_BoxNo โ€” program only
FileFile, XML_Document, Map_FileVia file system
ODBCConnection, Select_QueryVia database
ArraysReal[100], Dynamic_ElementNo โ€” program only

Mathematical Variable Types

Standard variables for arithmetic calculations. They exist only during macro execution.

TypeDescriptionExample
Integer32-bit signed whole number-1, 0, 76875
Integer6464-bit signed whole number123LL, -123456789123
Real64-bit IEEE floating point (~14 significant figures)-1.0, 3.14, 1.0e+6
TextA sequence of characters"Hello"
Vector2Two Reals (X, Y)
Vector3Three Reals (X, Y, Z)
Vector4Four Reals (X, Y, Z, W)
Matrix33ร—3 matrix of Reals (9 values)
Matrix44ร—4 matrix of Reals (16 values)

Automatic Promotions

The following promotions happen automatically when matching function arguments or return types:

FromTo
IntegerReal, Integer64
Integer64Real, Integer
RealInteger, Integer64
Vector2Vector3
Vector3Vector4, Vector2
Vector4Vector3
Note: In binary operations with mixed types the result is the higher type: 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.

TypeDescription
Point3D point with x, y, z coordinates
Line3D line joining two Points
ArcA helix: projects onto a circle in the (x,y) plane, with linearly interpolated z. Not a circle in 3D space.
SpiralA mathematically-defined transition curve (clothoid or cubic parabola) with continuously varying radius
ParabolaA vertical geometry parabola in the (chainage, height) plane
SegmentA 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.

A handle merely points to project data. Setting a handle to null does not change any data โ€” the handle simply points to nothing.
TypeDescription
ElementHandle to a 12d Model string/element (Super, Arc, Circle, Drainage, Tin, etc.)
TinHandle to a triangulated irregular network
ModelHandle to a 12d Model model (layer/group of elements)
ViewHandle to a 12d Model view
Macro_Function / FunctionHandle to a 12d Model user-defined function
Undo_ListA list for combining undo operations

Element Types

The type of an Element is returned by Get_type(Element elt, Text &type):

Element TypeDescription
SuperGeneral string with at least (x,y,z,radius) at each vertex โ€” preferred type
Super AlignmentString with full horizontal geometry via intersection point methods
ArcArc in (x,y) plane with linear z interpolation
CircleCircle in (x,y) plane with constant z
TextString with text at a vertex
TinTriangulated Irregular Network
DrainageDrainage/sewer element
PipelineAlignment string with diameter
Plot FrameElement 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.

TypeDescription
UidUnique identifier for entities in the 12d Model database
GuidGlobal unique identifier for a 12d Model project
AttributesHandle to a user-defined attribute structure (attachable to Projects, Models, Elements)
SDR_AttributeSpecial attributes for the 12d Survey Data Reduction process
BlobBinary data object
Attribute_BlobBinary attribute object
Screen_TextText displayed on screen
Textstyle_DataHolds text formatting: colour, textstyle, justification, height
Equality_LabelHolds information for labelling text as an equality
UndoHolds 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

TypeDescription
PanelTop-level window container for a macro's GUI
WidgetBase type for all UI controls
Vertical_GroupStacks widgets vertically
Horizontal_GroupArranges widgets horizontally
Widget_PagesMulti-page panel tabs
MenuUser-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

TypeDescription
FileA standard file unit for reading/writing files
Map_FileA file for mapping element properties
Plot_Parameter_FileA file for plot parameters
XML_DocumentFile contents structured as an XML document
XML_NodeA node within an XML document

ODBC Database Variable Types

These types provide access to external ODBC databases from within a macro.

TypeDescription
ConnectionConnection to an ODBC data source
Select_QueryRetrieve data from the database
Insert_QueryAdd data to the database
Update_QueryUpdate data in the database
Delete_QueryDelete data from the database
Database_ResultHolds the result set from a query
TransactionDatabase transaction management
Parameter_CollectionQuery parameters
Query_ConditionConditions for a query
Manual_ConditionManually 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
โš  C++ Difference: Array indices in 12dPL start at 1, not 0.

Dynamic Arrays

Dynamic arrays can grow or shrink at runtime. Items are accessed through function calls, not subscript notation.

TypeDescription
Dynamic_ElementVariable-length array of Elements
Dynamic_IntegerVariable-length array of Integers
Dynamic_Integer64Variable-length array of 64-bit Integers
Dynamic_RealVariable-length array of Reals
Dynamic_TextVariable-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
EscapeMeaning
\nNewline
\"Double quote
\\Backslash

Operators

Arithmetic Operators

OperatorMeaningNotes
+Addition
-Subtraction
*MultiplicationAlso dot product for vectors, matrix multiply
/DivisionInteger division truncates the fractional part
%ModulusInteger remainder: 7 % 3 == 1
^Cross productFor Vector2 and Vector3 only

Relational Operators

OperatorMeaning
==Equal to
!=Not equal to
<Less than
<=Less than or equal to
>Greater than
>=Greater than or equal to

Logical Operators

OperatorMeaning
&&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

OperatorMeaning
&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)

OperatorsAssociativity
() []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.

12dPL Difference from C++: Statements after each 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");
Restriction: A 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.

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);
}
Note: Prototypes can appear more than once in a file. The 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");
Note: Fixed arrays are always passed by reference. Dynamic arrays are also always by reference.

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
}
Warning: If more than one overload matches (due to automatic promotions), the compiler raises an error. Use a temporary variable to force the correct type.

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:

ScopeDescription
LocalDeclared in a block โ€” accessible in that block and any nested blocks after the declaration
FunctionLabels only โ€” accessible anywhere in the enclosing function
GlobalDeclared 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;
    }
}
Avoid reusing the same variable name in nested blocks โ€” the inner declaration hides the outer one.

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

CategoryDescription
TextString manipulation, conversion, formatting
MathsTrigonometry, logarithms, rounding, etc.
Input / OutputConsole output, file reading/writing, clipboard
SystemDate/time, process management, system queries
Dynamic ArraysAdd, get, set, clear dynamic arrays
Points & GeometryPoints, lines, arcs, spirals, segments
Segment GeometryLength, area, distance, offset, intersection
Vectors & MatricesDot product, cross product, transforms
ColoursColour creation and manipulation
ProjectProject access and properties
ModelsCreate, delete, navigate models
ViewsCreate, navigate views
ElementsCreate, modify, query all element types
Super StringsFull set of Super string manipulation functions
TinTIN creation, triangulation, queries
Panels & WidgetsCreate interactive GUI panels
XMLParse and generate XML
ODBCExternal database connectivity
AttributesUser-defined attributes on elements
UndosRegister undo operations

Text Functions

Commonly Used Functions

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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.

All · Showing 0 of 0

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).

All · 0 types

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

TypeCategoryDescription
voidSpecialUsed only for functions that return no value
IntegerMath32-bit signed integer
Integer64Math64-bit signed integer
RealMath64-bit IEEE floating point
TextMathString of characters
Vector2Math2D vector (X,Y)
Vector3Math3D vector (X,Y,Z)
Vector4Math4D vector (X,Y,Z,W)
Matrix3Math3ร—3 matrix
Matrix4Math4ร—4 matrix
PointGeometric3D point (temporary)
LineGeometric3D line (temporary)
ArcGeometricHelix / plan-circle (temporary)
SpiralGeometricTransition curve (temporary)
ParabolaGeometricVertical parabola (temporary)
SegmentGeometricUnion of Point/Line/Arc/Parabola/Spiral
ElementDB HandleHandle to 12d Model string/element
TinDB HandleHandle to triangulated irregular network
ModelDB HandleHandle to a 12d Model model
ViewDB HandleHandle to a 12d Model view
Macro_FunctionDB HandleHandle to a 12d Model function
Undo_ListDB HandleList for combining undos
UidInternalUnique ID for a database entity
GuidInternalGlobal unique ID for a project
AttributesInternalUser-defined attribute structure handle
Textstyle_DataInternalText colour/style/height data
PanelInterfaceGUI panel container
WidgetInterfaceBase UI control type
ButtonInterfaceClickable button
Message_BoxInterfaceRead-only text display area
Input_BoxInterfaceFree-text input field
FileFileFile read/write handle
XML_DocumentFileXML document handle
ConnectionODBCExternal database connection
Dynamic_ElementArrayDynamic array of Elements
Dynamic_RealArrayDynamic array of Reals
Dynamic_IntegerArrayDynamic array of Integers
Dynamic_TextArrayDynamic 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.