Layout
Set your editor to use 4-character-wide tabs. Use tabs to align expressions to each other where needed. Use space to align coordinates with and without – sign below each other.
hotspot2 -overhang, 0, unID, width, 1 + 128 : unID = unID + 1
hotspot2 -overhang, -width, unID, width, 2 : unID = unID + 1
hotspot2 -overhang, 1, unID, width, 3 : unID = unID + 1
To improve code readability, it is essential to express the hierarchy of nested statements. Code editors usually support folding code blocks based on indentation.
Recommended indentation of code blocks:
if condition1 then
...
else
...
endif
if condition2 then
if condition3 then
...
else
...
endif
if condition4 then
...
endif
else
...
endif
for i = initialValue to endValue
...
next i
do
...
for i = initialValue to endValue
...
next i
...
bCondition = ...
...
while bCondition
group "hole"
...
endgroup
cutform ...
...
cutend
Do not use indentation after transformations.
Sometimes a cut… command has to be conditional, do not indent the cut model in this case.
Use empty lines to emphasize closely related blocks of code. Do not over-use empty lines, too much scrolling degrades readability.
Write one statement per line. Exceptions are incrementing array indices where a loop is not suitable (HOTSPOT, UI_LISTITEM, array definitions).
Structure
Short and/or simple scripts can be of linear structure which makes them clearer. Subroutines are only needed when a calculation or model generation is done more than once.
It is an important principle to avoid coding the same – or any similar – thing twice. Redundancy will make the later changes much more difficult.
Avoid coding deep choice branches by preparing the data for a calculation or generation command in smaller, more general steps, introducing layers of abstraction with subroutines.
Split long code – longer than 1-2 screens or 100 lines – into subroutines that work at the same level of abstraction and handle only related data.
Calculate complex values only once to minimize redundancy and store them as variables or in the transformation stack (ADD, ROT, etc.).
Calculate values that are used locally before the block of use. Calculate values, initialize constants that are used throughout the script as early as possible at the start of the script.
Use drawing/modeling/hotspot commands at the local origin, unless transforming geometric parameters would not be feasible.
Macro calls with long parameter lists can be placed into subroutines for more compact code.
Use “” for non-localized strings (e.g. macro calls, parameter names). For localization _(”) can be used in .libpack format (e.g. strings shown on the UI).
Generalized solution that can be reused in other objects too:
add2 left, 0
_width = right - left
if bOnHomeStory then
line_type linetypeContour
fill gs_fill_type
_fillPen = gs_fill_pen
_fillBGPen = gs_back_pen
_height = depth
_mask = 1 + 2 + 4 + 8 ! bottom, left, right
gosub "DrawFilledRectangleWithMaskedContour"
endif
if (bOnUpperStory or bOnAboveUpper) and bDrawContBB then
line_type linetypeBelow
fill filltypeBelow
_fillPen = penFillBelow
_fillBGPen = penFillBackBelow
_height = depth / 2
_mask = 1 + 2 + 8 ! bottom, left, right
gosub "DrawFilledRectangleWithMaskedContour"
add2 0, _height / 2
_fillBGPen = 0
_mask = 2 + 4 + 8 ! top, left, right
gosub "DrawFilledRectangleWithMaskedContour"
del 1
endif
del 1
! ==============================================================================
end ! end ! end ! end ! end ! end ! end ! end ! end ! end ! end ! end ! end !
! ==============================================================================
! ==============================================================================
"DrawFilledRectangleWithMaskedContour":
! ------------------------------------------------------------------------------
! draws a rectangle with fill at (0, 0)
! input:
! _mask which side contours to draw 1 - bottom
! 2 - left
! 4 - top
! 8 - right
! _width
! _height
! _fillPen
! _fillBGPen
! ==============================================================================
poly2_b 5, 3, _fillPen, _fillBGPen,
0, _height, bittest(_mask, 1), ! left
0, 0, bittest(_mask, 0), ! bottom
_width, 0, bittest(_mask, 3), ! right
_width, _height, bittest(_mask, 2), ! top,
0, _height, -1
return
! instead of:
if bOnHomeStory then
line_type linetypeContour
fill gs_fill_type
poly2_b 5, 3, gs_fill_pen, gs_back_pen,
left, 0, 1,
left, depth, 1,
right, depth, 1,
right, 0, 1,
left, 0, -1
endif
if (bOnUpperStory or bOnAboveUpper) and bDrawContBB then
line_type linetypeBelow
fill filltypeBelow
poly2_b 5, 3, penFillBelow, penFillBackBelow,
left, 0, 1,
left, depth / 2, 0,
right, depth / 2, 1,
right, 0, 1,
left, 0, -1
poly2_b 5, 3, penFillBelow, 0,
left, depth / 2, 1,
left, depth, 1,
right, depth, 1,
right, depth / 2, 0,
left, depth / 2, -1
endif