Master script
Master script is not a script context
When writing the master script you should keep in mind that it will be evaluated before the run of each script, in the context of that script. It doesn’t have a “memory” between different script runs, practically the master script is prepended to each script’s code.
This implies the following things:
- Global variables can have different values in each script context, thus the same code can execute differently
- Placing parameter definitions and calculations used by multiple scripts in the master script is a good idea: it reduces code complexity.
- A non-empty parameter buffer will have an effect on all scripts.
- Subroutines can be shared between scripts
Subroutines in master script
Subroutines in master script can be used from any other script too. A special coding pattern is needed to avoid running the subroutines without calling, but not ending the script execution prematurely:
...
! writing an end statement here would end execution
! without running non-master scripts
goto "MasterEnd"
! ==============================================================================
end ! end ! end ! end ! end ! end ! end ! end ! end ! end ! end ! end ! end !
! ==============================================================================
! ==============================================================================
"Subroutine":
! ==============================================================================
! can be called from other scripts, returns to other scripts
return
! ==============================================================================
"MasterEnd":
! ==============================================================================
! execution is continued in non-master scripts
2D/3D scripts
Fragments/binary model
These are a feature intended for automatic model conversion/generation. Using them for manually created objects is not recommended:
- A script is much more customizable than a fragment. Models/drawings can be dragged from the plan into the scripts to generate code.
- Binary symbols aren’t editable.
- In a binary 2D symbol, the curved fills aren’t stretched correctly.
Hotspot IDs
If an object is supposed to be dimensionable, use an ID for each of its hotspots/hotlines/hotarcs – even the ones that make no sense to be dimensioned. Unidentified hotspots are given an ID by Archicad and can overlap IDs in the code.
IDs shouldn’t be affected by branch conditions. When using a continuously increased ID variable, increase it on else branches too.
if A > 1 then
if B > 0 then
hotspot2 A, B, unID : unID = unID + 1
else
unID = unID + 1
endif
hotspot2 A, 0, unID : unID = unID + 1
else
unID = unID + 1
hotspot2 0, 0, unID : unID = unID + 1
endif
If IDs are affected by loop length, let them be the largest ones, or reserve enough space for the maximum possible by input.
Undo transformations early
When you do not need a transformation anymore, undo it using DEL
.
Temporary transformations done in a code block should be deleted before the end of the code block. Temporary transformations done in a loop can be deleted immediately after the end of the code block using a loop counter.
Do this for the top level of the script as well to make further modifications on the object easier.
Do not use DEL TOP
command to make later modifications easier. Use variables to count conditional transformations to be undone late
addz -1
for n = 1 to 3
if p then
addz 1
sphere 0.01
del 1
endif
rotz 30
addx 1
sphere 0.1
next n
del 2 * (n - 1) ! the loop variable gets incremented after the last run
sphere 0.01
del 1
3D script
Wrap texture using transformation and coor{3}
For code clarity, use a fixed COOR{3}
command with transformations defined before it.
In general, separate bodies which require different texture coordinate systems with a body -1 command.
define texture "Own Tile" "Tile Texture",
1, 1, 128 + 256, 0
define material "Tile" 21,
0.7, 0.7, 1,
0.15, 0.95, 0, 0.0,
0, 0,
ind(fill, ""), 1,
ind(texture, "Own Tile")
material "Tile"
block 1, 1, 1
add 0.5, 0.5, 0.5
_wrap = 2 ! box
gosub "AlignTexture"
del 1
end
"AlignTexture":
coor{3} _wrap, 0,
0, 0, 0, ! origin
1, 0, 0, ! x
0, 1, 0, ! y
0, 0, 1 ! z
body -1
return
Wrap texture often
On complicated models, texture wrapping should be specified after each modeling command. Archicad closes bodies after a specific number of primitive faces, and texture wrapping won’t affect those.
Close bodies between different materials
Use the body -1 command before changing the material. This is necessary for correct cut surfaces. The Internal Rendering Engine (used on sections, elevations) needs it for accurate shadow casting of solid and transparent parts of an object (e.g., window sash with grilles).
prism_ 10, 0.1,
0, 0, 15,
1, 0, 15,
1, 1, 15,
0, 1, 15,
0, 0, -1,
0.1, 0.1, 15,
0.9, 0.1, 15,
0.9, 0.9, 15,
0.1, 0.9, 15,
0.1, 0.1, -1
body -1
material "Blue Glass"
prism_ 5, 0.1,
0.1, 0.1, 15,
0.9, 0.1, 15,
0.9, 0.9, 15,
0.1, 0.9, 15,
0.1, 0.1, -1
Parameter script
Hide the old parameter list
When all parameters appear on the graphical interface, hide the All parameters… tabpage. Make its visibility dependent on GLOB_DIAGNOSTICS_MODE for easier debugging.
if not(GLOB_DIAGNOSTICS_MODE) then hideparameter all "A", "B", "ZZYZX"
Run only once
Always set parameter scripts to run only once. To make the parameter script compatible with this setting, follow the rules described in the sub-sections.
Parameter changes are not immediate
Parameter names written in the script can be thought of as variables copied at script start with the same name. These variables aren’t affected by the values and parameters commands, and parameters aren’t affected by the variables’ value changes. VALUES
and PARAMETERS
commands only take effect after the end of the parameter script.
Using parameter-named-variables in commands that only change parameter values can quickly lead to confusion.
When parameter values need to be changed, copy them to variables prefixed with _ and use VALUES
and PARAMETERS
commands to alter the parameter’s value when the calculations are complete. Because the parameters will only change after the end of the parameter script, use the variables in the script. This is the key to running the parameter script only once.
Setting parameters
When calculating parameter connections, calculate the variable’s value first, then make the parameter equal to its variable value.
_A = A
...
_halfA = _A / 2 ! Use _A to make clear it contains a value copied from the
! parameter A before parameters A = ... commands.
! A might change after the end of the script
! even if it is on a previous line.
parameters halfA = _halfA
... ! use _halfA later in the script, halfA will change only
! after the end of the script
Defining parameter restrictions
When limiting a parameter’s value with the range keyword, use variables to determine its minimum and/or maximum values. After the range command, overwrite the variable copied from the parameter if it exceeds the limits defined by these values.
_A = A ... _minA = 0.2 values "A" range [_minA, ) if _A < _minA then _A = _minA
Similarly, when distinct VALUES are defined, make sure the variable’s value in the script matches the parameter’s possibilities.
Range open intervals
As well as with closed interval range commands, the variables have to be calculated when using open intervals. When setting a parameter lower than its open interval minimum (or higher than its open interval maximum), Archicad sets the value to be above (or below) the open interval minimum/maximum with 10 mm (or 0.01 degrees for angle type parameters). To keep variables in sync with this method, use 0.01 to calculate the modified values.
_A = A
...
_minA = 0.2
values "A" range (_minA, )
if not(_A > _minA) then _A = _minA + 0.01 ! entering 0.205 would be allowed,
! it is just a default offset
Try to group commands in this order
- Set value ranges
- Calculate parameter connections
- Lock/hide parameters
- Handle UI jump buttons
Define all ranges
Define the valid value range for these parameters using the VALUES command:
- length (probably not 0)
- used in divisions (definitely not 0)
- integer used for resolution (always greater than 3)
- angle (with care about 90-degree increment validity)
- integer used for pens
- pen (disable background colors for foreground/contour pens)
Parameter name string comparison
Parameter names are case-insensitive, but string contents and string comparisons aren’t. Take care when using GLOB_MODPAR_NAME: always use parameter names with the same case.
if GLOB_MODPAR_NAME = "a" then ... ! always false
Font type names
If you want to have a string parameter – named stFont
in the sample – for setting the font type for a text, use the following value list definition to get a platform-independent sound solution. CUSTOM
value is needed to deal with missing or unexpected font types.
dim _stFontNames[]
request ("FONTNAMES_LIST", "", _stFontNames)
values "stFont" _stFontNames, CUSTOM
This request disables background conversion for the objects which use it, so do this in a “Library Master” subtype. Every loaded library part with the same “stFont” parameter will automatically receive the same value list.
Use font parameters already defined in the Archicad Library or the built-in library’s Library Master objects.
UI script
Hierarchical tabpage IDs
To allow easier addition/removal of tabpages in a hierarchical structure, define the IDs of different levels on a logarithmic scale:
! =============================================================================
! Tabpage Structure Definition
! =============================================================================
TABID_ROOT = -1
TABID_LEVEL1_PAGE1 = 1000
TABID_LEVEL2_PAGE1 = 1100
TABID_LEVEL3_PAGE1 = 1110
TABID_LEVEL3_PAGE2 = 1120
TABID_LEVEL4_PAGE1 = 1121
TABID_LEVEL4_PAGE2 = 1122
TABID_LEVEL2_PAGE2 = 1200
TABID_LEVEL1_PAGE2 = 2000
Tabpages as subroutines
When a script creates multiple tabpages, organize them into separate subroutines:
ui_page TABID_PAGE1, TABID_ROOT, _stTabTitle1, _stTabIcon1
if gs_ui_current_page = TABID_PAGE1 then gosub "TabPage1"
Many tabpages might be easier to handle in a loop:
dict _tabs : i = 1
_tabs.id[i] = TABID_1 : _tabs.title[i]= _(`Page1`) : _tabs.sub[i] = "TabPage1"
_tabs.parent[i]= TABID_ROOT : _tabs.icon[i] = "TabIcon1"
i = i + 1
_tabs.id[i] = TABID_2 : _tabs.title[i] = _(`Page2`) : _tabs.sub[i] = "TabPage2"
_tabs.parent[i]= TABID_1 : _tabs.icon[i] = "TabIcon2"
i = i + 1
...
for i = 1 to vardim1(_tabs.id)
ui_page _tabs.id[i], _tabs.parent[i], _tabs.title[i], _tabs.icon[i]
if gs_ui_current_page = _tabs.id[i] then gosub _tabs.sub[i]
next i
Use relative coordinates
Position UI elements relative to each other to allow easier layout changes, e.g. increasing the size of a picture or adding a new control in the middle of the dialog.
Outfields
Always define width/height.
Infields
The recommended style for ui_infield commands is:
- position and size in first row
- next lines start one ident deeper
- comment method and picture IDs
- write 0 or “” for parameters which are unused by the infield method
ui_infield{3} "bBool", _xPos1, _yCurr - 4, _boolWdt, _inFldHgt,
7, ! Checkbox with text
"", 0, 0,
0, 0, 0, 0,
"", _(`Boolean Parameter Description`), 0,
"", _(`Boolean Parameter Description`), 1
ui_infield{3} "iType", _xPos2, _yCurr - 4, _boolWdt, _inFldHgt,
1, ! List view
2, 3, 1, ! 2: panel_type_hg_hl(1)
62, 110, 36, 80,
1, _(`Rectangular`), DOOR_RECTANGULAR,
2, _(`Curved Top`), DOOR_CURVED_TOP,
3, _(`Custom Door Leaf`), DOOR_CUSTOM
Baseline alignment
To align the baseline of text in infields and outfields on both platforms without writing platform-dependent code, the best practice is a 15 px high outfield and a 19 px high infield aligned at the bottom.
DYIO = 4 ! infield-outfield y position difference
ui_outfield "Example Input", _xStart, _yCurr,
_outFieldLength, _outfieldHeight
ui_infield "exampleInput", _xStart + _outFieldLength + _xGap, _yCurr - DYIO,
_inFieldLength, _infieldHeight
Using images
When using an external image referred to by its file name, omit the file extension to avoid errors stemming from svg-tif conversion. Add the FILE_DEPENDENCE
command to make sure they are saved in archive format with the object.
When using internal image referred to by its index, write a comment with its source file name on the same line.
Migration scripts
These scripts have a recommended form of separators and structures. Use the templates of Basic Technical Standards: FWM script, BWM script.