Next Previous Contents

## 6. The Tcl Scripting Interface

The scripting interface is mainly a bunch of Tcl procedures and Tcl commands that a big part of Ayam uses internally.

Using Tcl, you could directly modify the code Ayam consists of. This is, however, not recommended for good reasons. So watch out for already existing procedures and commands when implementing your own! Using procedures and commands not listed in this documentation is dangerous too. Implementation and interfaces of that commands may change unnoticed in future versions.

The scripting interface may be used directly from the console of Ayam. You can, of course, also write procedures in your own Tcl script files, that may be loaded at any time into Ayam using the console and the Tcl command `"source"`. You can also arrange for a script to be executed automatically on startup using the preference setting `"Main/Scripts"`. In contrast to other modelling environments, in Ayam there is a third way to run scripts. In Ayam, scripts may also be attached to script objects and run when the notification mechanism updates the scene. See also section Script object.

Note that most of the scripting interface commands listed in this documentation work in the background, without changing anything to the Ayam GUI and Ayam view windows, for the sake of execution speed. If you want your changes to become visible you have to update the various parts of the GUI (property GUIs, view windows) explicitly (see also section Updating the GUI). Since Ayam 1.13 it is also possible to automatically run GUI updating commands in the console by using `<Shift+Return>` instead of `<Return>` when issuing scripting interface commands.

If you want your changes to be undoable, you have to arrange for this manually too (see the documentation of the undo command: Undo).

From scripts it may be necessary to check wether an error occured during the execution of a command. All commands return TCL_OK in any case so checking their return value avails to nothing, but they set the global Tcl variable `"ay_error"` to a value higher than 1 if an error occured. You need to set it to zero before and check it after the operation in question to see whether the operation performed successfully:

    proc myProc { } {
      set ::ay_error 0
      copOb
      if { $::ay_error > 1 } {
        ayError 2 "myProc" "Error copying object!"
      }
    }

## 6.1 Global Variables and Arrays

Several global variables exist in the Ayam Tcl context, that may be useful for scripts.

### Global Variables

- The `"ay_error"` variable holds the current error state. See also section Reporting Errors.
- The variable `"i"` is used by all `"forAll"` command variants. See also section Applying Commands to a Number of Objects.

### The Global Array ay

The global array `"ay"` holds application state variables. Furthermore, you can find the paths to important widgets (e.g. the tree widget for the object hierarchy or the currently active view) in this array. Use `"parray ay"` in the console to see what is there. More documentation to come.

### The Global Array ayprefs

The global array `"ayprefs"` holds preferences data. The complete array is saved in the `"ayamrc"` file upon exit, so be careful when adding new entries. You can reset your `"ayamrc"` file anytime using the command line option `"-failsafe"`. See also section Ayamrc File. Use `"parray ayprefs"` in the console to see what is there. More documentation to come.

### The Global Property Management and Data Arrays

For every property, a corresponding global array exists, where the data of the property is saved. This global array only holds useful data when the respective property GUI is active, or when it has been filled explicitly by the so called get-property callback. The data may be transferred back to the selected object using the so called set-property callback. The names of the array and the callbacks may be inferred from another global array that is always named like the property itself, e.g. for the tags property the following global array `"Tags"` is defined:

    Tags {
    arr   tagsPropData
    sproc setTagsp
    gproc getTagsp
    w     fTagsAttr
    }

The entry arr designates the name of the global property data array. If sproc or gproc are empty (`""`), a standard callback named `"setProp"` or `"getProp"` should be used to get or set the property values. Otherwise sproc and gproc designate the set-property and get-property callbacks respectively.

The following global arrays and callbacks to get or set the data exist:

property | array | get-property callback | set-property callback
Transformations | transfPropData | getTrafo | setTrafo
Attributes | attrPropData | getAttr | setAttrp
Material | matPropData | getMat | setMat
Tags | tagsPropData | getTagsp | setTagsp

Property Arrays and Callbacks

See also section Manipulating Properties for more information on how to edit property values from the scripting interface.

## 6.2 Index of Procedures and Commands

This section provides documentation on the most important scripting interface commands and procedures of Ayam sorted by category.

### Getting Help on Scripting Interface Commands

Since Ayam 1.8.2 a scripting interface command named `"help"` is available, that displays the help of scripting interface commands using a web browser (similar to the `"Help on Object"` feature):

- Synopsis: `"help command"`
- Description: Fire up a web browser and display the help for the designated Ayam scripting interface command.
- Example: `"help help"` displays the help of the help command.

### Creating Objects

To create new objects the `"crtOb"` command can be used.

- Synopsis: `"crtOb type [args]"`
- Description: New objects may be created with the command `"crtOb"`, type may be derived from the type name, as displayed in the tree view.

  Depending on the type, further arguments may (or have to) be given, some object types expect other objects to be selected:

  - `"NCurve"`: NURBS curves accept a single integer as length of the new curve, the length defaults to 4. Example: `"crtOb NCurve -length 10; uS; rV"`
  - `"NPatch"`: NURBS patches accept two integers as width and height of the new patch, width and height both default to 4. Example: `"crtOb NPatch -width 2 -height 2; uS; rV"`
  - `"Level"`: Levels must be given an additional argument determining the type of the new level, this argument may be one of: `"0"` (level), `"1"` (union), `"2"` (intersection), `"3"` (difference), `"4"` (primitive).
  - `"Material"`: Materials must be given an additional argument giving the name of the new material. Example: `"crtOb Material default; uS; rV"`
  - `"Instance"`: creates an instance of the selected object.
  - ...
- Example: Create a sphere and update the GUI: `"crtOb Sphere; uS; rV"`.

### Manipulating the Selection

These commands are probably the most important ones, because many other scripting interface commands operate on selected objects only:

selOb - select object(s):

- Synopsis: `"selOb [index]"`
- Description: Use this command to set or clear the current selection, index may be an ordered list of indizes, a single index or empty. If no index is given, the current selection will be cleared.
- Examples: `"selOb"` clears the current selection, `"selOb 0"` selects the first object in the current level, `"selOb 0 1"` selects the first two objects in the current level.

withOb - execute a command on certain selected object(s):

- Synopsis: `"withOb index [do] command"`
- Description: Use this command to execute command on a single object (designated by index) from a multiple selection without changing the selection state of any objects.
- Example: `"withOb 2 {movOb 0 1 0}"` moves the third object from multiple selected objects. All objects stay selected.

sL - select last object:

- Synopsis: `"sL"`
- Description: Select the last object in the current level and update the GUI. This command is often called in a sequence after creating a new object like this:

      # create object
      crtOb NCurve
      # update tree
      uCR
      # select new object
      sL

hSL - hidden select last object:

- Synopsis: `"hSL"`
- Description: Select the last object in the current level but do not update the GUI. This command is mainly for use in script objects script code.

### Manipulating Properties

Since Ayam 1.9 two new commands are implemented that ease the manipulation of property values from the scripting interface:

getProperty - get single property value

- Synopsis: `"getProperty propname(elemname) varname"`
- Description: This command gets a single property element named elemname from the property named propname of the currently selected object and writes the result into the variable named varname.
- Notes: In contrast to many other helper commands, the variable varname does not have to be global. This command runs more slowly than accessing the data array that is associated with a property and calling the appropriate get-procedure directly. See below for more information regarding direct access of property values.
- Example: Given that a single Sphere object is selected, its radius may be retrieved in the variable `"r"` easily using the command `"getProperty SphereAttr(Radius) r"`

setProperty - set single property value

- Synopsis: `"setProperty propname(elemname) value"`
- Description: This command sets a single property element named elemname of the property named propname for the currently selected object to the new value given in value.
- Notes: This command runs more slowly than accessing the data array that is associated with a property and calling the appropriate set-procedure directly. See below for more information regarding direct access of property values.
- Example: Given that a single Sphere object is selected, its radius may be set to the new value `"3.0"` easily using the command `"setProperty SphereAttr(Radius) 3.0"`

In contrast to `"setProperty"`, here is an equivalent example for the direct (fast) access of property values:

    getProp
    set SphereAttrData(Radius) 3.0
    setProp

See also section Global Property Management and Data Arrays.

### Clipboard Operations

These commands operate the object clipboard:

copOb - copy object:

- Synopsis: `"copOb"`
- Description: Copy the selected object(s) to the object clipboard.

cutOb - cut object:

- Synopsis: `"cutOb"`
- Description: Move the selected object(s) into the object clipboard.

pasOb - paste object:

- Synopsis: `"pasOb"`
- Description: Copy the selected object(s) from the object clipboard to the current level.

delOb - delete object:

- Synopsis: `"delOb"`
- Description: Delete the selected object(s) from the scene.

cmovOb - paste (move) object:

- Synopsis: `"cmovOb"`
- Description: Move the objects from the object clipboard to the current level.

The following commands operate the property clipboard, which is totally independent from the object clipboard.

pclip_copy/copyProp - copy a property to the property clipboard

- Synopsis: `"pclip_copy mode"` or `"copyProp mode"`
- Description: Copy the currently selected property from the currently selected object to the property clipboard. If mode is 0, omit all marked entries, if mode is 1 copy just marked entries. Note that you may call this procedure also using the shortcut `"copyProp"`.

pclip_paste/pasteProp - paste a property

- Synopsis: `"pclip_paste"` or `"pasteProp"`
- Description: Copy the property from the property clipboard to the currently selected object. Note that you may call this procedure also using the shortcut `"pasteProp"`.

### Hierarchy Operations

These commands manipulate the current level of Ayam:

goDown:

- Synopsis: `"goDown index"`
- Description: Enter the object determined by index. If index is 0 and the current level is inside some other object (not the root) the parent level will be entered instead.

goUp:

- Synopsis: `"goUp"`
- Description: Go one level up in the object hierarchy.

goTop:

- Synopsis: `"goTop"`
- Description: Go to the top level of the object hierarchy.

### Transformations

These commands transform objects or selected points of objects:

movOb - move objects:

- Synopsis: `"movOb dx dy dz"`
- Description: Move the selected object(s) by dx in direction of the objects X axis, by dy in direction of the objects Y axis and by dz in direction of the objects Z axis.

rotOb - rotate objects:

- Synopsis: `"rotOb dx dy dz"`
- Description: Rotate the selected object(s) by dx degrees around the objects X axis, then by dy degrees around objects Y axis and then by dz degrees around the objects Z axis. Note the order of the rotations!

scalOb - scale objects:

- Synopsis: `"scalOb dx dy dz"`
- Description: Scale the selected object(s) by a factor of dx in direction of the objects X axis, by a factor of dy in direction of the objects Y axis and by a factor of dz in direction of the objects Z axis.
- Note: A scale factor of zero is generally a bad idea and thus will be changed to 1.0 silently!

movSel - move selected points:

- Synopsis: `"movSel dx dy dz"`
- Description: Move the selected points by dx in direction of the objects X axis, by dy in direction of the objects Y axis and by dz in direction of the objects Z axis.

rotSel - rotate selected points:

- Synopsis: `"rotSel dx dy dz"`
- Description: Rotate the selected points by dx degrees around the objects X axis then by dy degrees around objects Y axis and then by dz degrees around the objects Z axis. Note the order of the rotations!

scalSel - scale selected points:

- Synopsis: `"scalSel dx dy dz"`
- Description: Scale the selected points by a factor of dx in direction of the objects X axis, by a factor of dy in direction of the objects Y axis and by a factor of dz in direction of the objects Z axis.
- Note: A scale factor of zero is generally a bad idea and thus will be changed to 1.0 silently!

delegTrafo - delegate transformations:

- Synopsis: `"delegTrafo"`
- Description: delegates the transformations associated with the selected objects to their child objects. Additionally, the transformations of the selected objects will be reset to the default values.

applyTrafo - apply transformations:

- Synopsis: `"applyTrafo sel|all"`
- Description: applies the transformations encoded in the transformation attributes of the selected objects to the points (either all points, or just the selected ones if there are any) of those objects. Additionally, the transformations of the selected objects will be reset to the default values.

### Manipulating Shaders

These commands operate the shader properties:

shaderSet:

- Synopsis: `"shaderSet shadertype [varname]"`
- Description: Set the shader of type shadertype for the selected object. Type may be one of `"surface"`, `"displacement"`, `"light"`, `"imager"`, `"atmosphere"`, `"exterior"` or `"interior"`. If varname is not given, the shader in question is deleted from the object instead.

shaderGet:

- Synopsis: `"shaderGet shadertype varname"`
- Description: Get the shader of type shadertype for the selected object. Type may be one of `"surface"`, `"displacement"`, `"light"`, `"imager"`, `"atmosphere"`, `"exterior"` or `"interior"`. The shader will be written to an array pointed to by varname.

### Manipulating Tags

These commands may be used to modify the tags of an object:

addTag:

- Synopsis: `"addTag type value"`
- Description: Add a tag with type-string type and value-string value to the currently selected objects(s). It is legal to deliver `""` as value parameter. This is e.g. needed for the `"NoExport"` tag.

delTags:

- Synopsis: `"delTags type"`
- Description: Delete all tags of type-string type from the currently selected objects(s). If type is `"all"`, all tags are deleted from the currently selected objects(s).

getTags:

- Synopsis: `"getTags tvname vvname"`
- Description: Get all tags from the currently selected objects and put them as lists into two variables named tvname for the tag type-strings and vvname for the tag value-strings.

setTags:

- Synopsis: `"setTags tags"`
- Description: Clear all tags from the currently selected object and set new tags. The tag type-strings are taken from the list elements with even index numbers and the tag value-strings from the list elements with odd index numbers.

### Manipulating NURBS Curves and Surfaces

These are more specialized commands to change NURBS curve and surface properties:

clampNC - clamp NURBS curve:

- Synopsis: `"clampNC"`
- Description: Clamp the knot vector of the selected NURBS curves without changing the shape of the curves. The knot type of the clamped curve will be changed to `"Custom"` and the knots will have o equal values at start and end (where o is the order of the curve). See also section The Clamp Tool.

elevateNC - elevate NURBS curve:

- Synopsis: `"elevateNC n"`
- Description: Elevate the order of the selected NURBS curves without changing the shape of the curves by n. The knot type of the elevated curves will be changed to `"Custom"`. See also section The Elevate Tool.

insknNC - insert knot into NURBS curve:

- Synopsis: `"insknNC u r"`
- Description: Insert a new knot at the position specified by u (u must be in the valid range of the knot vector of the selected curves) r times. The valid range is determined by the current knot vector U as follows: `U[p] <= u <= U[n]`, where p is the degree (order-1) of the curve and n is the length of the curve. The knot type of the curves will always be changed to custom but the shape of the curves will not change! See also section The Insert Knot Tool.

remknNC - remove knot from NURBS curve:

- Synopsis: `"remknNC u r [tol]"`
- Description: Remove a knot at the position specified by u (u must be in the valid range of the knot vector of the selected curve) r times from the curve. Note that the shape of the curve may be changed by this tool unless the parameter tol is specified. If tol is specified the new curve does not deviate from the original curve more than tol in any point on the curve. If the knot can not be removed r times due to the tolerance, an error is reported and the original curve is left unchanged. See also section The Remove Knot Tool.

refineNC - refine NURBS curve:

- Synopsis: `"refineNC [{u1 u2 un}]"`
- Description: Refine the knot vector of the selected NURBS curve without changing the shape of the curve with n new knots {u1 u2 un}. Or, if no list of new knots is given: add a new knot into each interval in the old knot vector. The knot type of the refined curve may be changed to `"Custom"`. See also section The Refine Tool.

coarsenNC - coarsen NURBS curve:

- Synopsis: `"coarsenNC"`
- Description: Remove every second control point from the selected NURBS curves. See also section The Coarsen Tool.

revert - revert curves:

- Synopsis: `"revert"`
- Description: Revert the direction of the selected NURBS curves and interpolating curves. See also section The Revert Tool.

revertU - revert surfaces:

- Synopsis: `"revertU"`
- Description: Revert the direction of the selected NURBS patches. See also section The Revert U Tool.

revertV - revert surfaces:

- Synopsis: `"revertV"`
- Description: Revert the direction of the selected NURBS patches. See also section The Revert V Tool.

rescaleKnNC - rescale knots of NURBS curves:

- Synopsis: `"rescaleKnNC [-r rmin rmax|-d mindist]"`
- Description: Rescale the knot vector(s) of the selected NURBS curve(s) to the range `[0.0, 1.0]` (if no argument is present) or to the range `[rmin, rmax]` if the `"-r"` argument is given or to the minimum distance mindist if the `"-d"` argument is used. Scaling to a minimum distance ensures that all knots (except for multiple knots) have a distance bigger than mindist afterwards. The knot type of the curve has to be `"Custom"`! This operation does not change the shape of the curve. See also section The Rescale Knots to Range Tool.

splitNC - split NURBS curve

- Synopsis: `"splitNC u"`
- Description: splits the selected NURBS curve at designated parametric value into two curves, creating one new curve and modifying the original selected curve. See also section The Split Tool.

toXYNC - move NURBS curve to XY plane

- Synopsis: `"toXYNC"`
- Description: moves the control points of the selected NURBS curve objects to its XY plane. See also section The To XY Tool.

trimNC - trim NURBS curve

- Synopsis: `"trimNC umin umax"`
- Description: trims the selected NURBS curve to the designated parametric range (umin-umax), modifying the original selected curve. See also section The Trim Tool.

clampNPU - clamp NURBS patch in u-direction:

- Synopsis: `"clampNPU"`
- Description: Clamp the u-direction knot vector of the selected NURBS patches without changing the shape of the patches. The knot type will be changed to `"Custom"` and the knots will have o equal values at start and end (where o is the order of the patch in u-direction). See also section The Patch Clamp Tool.

clampNPV - clamp NURBS patch in v-direction:

- Synopsis: `"clampNPV"`
- Description: Clamp the v-direction knot vector of the selected NURBS patches without changing the shape of the patches. The knot type will be changed to `"Custom"` and the knots will have o equal values at start and end (where o is the order of the patch in v-direction). See also section The Patch Clamp Tool.

rescaleKnNP - rescale knots of NURBS patches:

- Synopsis: `"rescaleKnNP [-r[u|v] rmin rmax|-d[u|v] mindist]"`
- Description: Rescale the knot vector(s) of the selected NURBS patch(es) to the range `[0.0, 1.0]` (if no argument is present) or to the range `[rmin, rmax]` if the `"-r"` argument is given or to the minimum distance mindist if the `"-d"` argument is used. The `"-ru"`, `"-rv"`, `"-du"`, and `"-dv"` variants scale only the designated dimension. Scaling to a minimum distance ensures that all knots (except for multiple knots) have a distance bigger than mindist afterwards. Trim curves, if present, will also be scaled to match the new range. The knot types of the patch have to be `"Custom"`! This operation does not change the shape of the patch. See also sections The Patch Rescale Knots to Range Tool and The Patch Rescale Knots to Mindist Tool.
- Example: `"rescaleKnNP -ru 0.2 0.3"` scales the u knot vector of the selected NURBS patch objects to the new range (0.2, 0.3).

insknNPU - insert knot into NURBS patch:

- Synopsis: `"insknNPU u r"`
- Description: Insert a new knot in u-direction at the position specified by u, r times. u must be in the valid range of the corresponding knot vector of the selected patches. The valid range is determined by the current knot vector U as follows: `U[p] <= u <= U[n]`, where p is the degree (order-1) of the patch in u-direction and n is the width of the patch. The u knot type of the patches will always be changed to `"Custom"` but the shape of the patches will not change! See also section The Patch Insert Knot Tool.

insknNPV - insert knot into NURBS patch:

- Synopsis: `"insknNPV v r"`
- Description: Insert a new knot in v-direction at the position specified by v, r times. v must be in the valid range of the corresponding knot vector of the selected patches. The valid range is determined by the current knot vector V as follows: `V[p] <= v <= V[n]`, where p is the degree (order-1) of the patch in v-direction and n is the height of the patch. The v knot type of the patches will always be changed to `"Custom"` but the shape of the patches will not change! See also section The Patch Insert Knot Tool.

splitNPU - split NURBS patch:

- Synopsis: `"splitNPU u"`
- Description: Splits the selected NURBPatch objects into two patches at parametric value u. See also section The Patch Split Tools.

splitNPV - split NURBS patch:

- Synopsis: `"splitNPV v"`
- Description: Splits the selected NURBPatch objects into two patches at parametric value v. See also section The Patch Split Tools.

extrNP - extract NURBS patch:

- Synopsis: `"extrNP umin umax vmin vmax"`
- Description: Extracts a sub-patch from the selected NURBPatch objects. The sub-patch is specified by the parametric values umin, umax, vmin, and vmax which have to be in the respective valid knot range. See also section The Extract Patch Tool.

splitNP - split NURBS patch:

- Synopsis: `"splitNP (u|v)"`
- Description: Splits the selected NURBPatch into NURBS curves, along parametric dimension u or v. See also section The Patch Split Tools.

buildNP - build NURBS patch:

- Synopsis: `"buildNPatch"`
- Description: Builds a NURBPatch from the selected NURBS curves. See also section The Build from Curves Tool.

### Manipulating Points

Use these two commands to read or manipulate single points of arbitrary objects. Note that the exact arguments needed depend on the type of the selected object, e.g. a NURBS curve requires just one index parameter (indexu), whereas a NURBS patch requires two index parameters (indexu and indexv).

getPnt:

- Synopsis: `"getPnt [-trafo|-p] indexu [indexv] varx vary varz [varw]"`
- Description: Get a control point of the currently selected object and write the coordinate values into the variables varx, vary, varz, and varw. If the special argument `"-trafo"` is given, the coordinates will additionally be transformed by the values given in the objects Transformation property. If the argument `"-p"` is given, the `"indexu"` and `"indexv"` values are interpreted as parametric values of a NURBS curve or surface and the corresponding point on the curve or surface is delivered in varx, vary, and varz.
- Examples: `"getPnt 1 x y z w"` gets the coordinate values of the second point of the selected NURBS curve and writes the values to the variables `"x y z w"`. `"getPnt -p 0.5 x y z w"` gets the curve point at parametric value `"0.5"` and writes the values to the variables `"x y z w"`.

setPnt:

- Synopsis: `"setPnt indexu [indexv] x y z [w]"`
- Description: Set a control point of the currently selected object to the coordinates x, y, z, and w.
- Example: `"setPnt 1 0.0 0.2 0.3 1.0"` sets the coordinate values of the second point of the selected NURBS curve object to `"0.0 0.2 0.3 1.0"`.

### Updating the GUI

These commands update various parts of the Ayam user interface:

rV - redraw all views:

- Synopsis: `"rV"`
- Description: Redraws all currently open views, except for iconified views and views where automatic redraw has been turned off.

uS - update select:

- Synopsis: `"uS [update_prop maintain_selection]"`
- Description: Update the object listbox or tree view after a change to the object hierarchy.

  If update_prop is 0 no update of the property GUIs will take place. If maintain_selection is 1 the old selection will be established again. If both arguments are omitted update_prop defaults to 1 and maintain_selection to 0.

- Deficiencies: uS completely removes the object tree from the tree widget and rebuilds it, which can be a very time consuming operation (depending on the complexity of the scene). There are some options to speed this process up:
  - If there were just changes to the current level (and below) the global array entry `"ay(ul)"` (UpdateLevel) may be set to the current level before calling `"uS"`. This will not remove and update the complete scene but just the part below `"ay(ul)"`. Example:

        global ay; set ay(ul) $ay(CurrentLevel); uS;

    .
  - If objects have been created and thus just need to be added to the current level of the object tree view, the command `"uCR"` may be used instead of `"uS"`.
  - If just names or types of objects of the current level changed, the command `"uCL cl"` may be used instead of `"uS"`.

uCL - update current level:

- Synopsis: `"uCL mode [args]"`
- Description: Update only the current level of the object listbox or tree view after changes. See also the discussion of `"uS"` above. The parameter `"mode"` may be "cl" or "cs", where "cl" is the normal operation mode, and "cs" just clears the selection.

uCR - update current level after create:

- Synopsis: `"uCR"`
- Description: Update only the current level of the object listbox or tree view after objects have been created and need to be added to the current level. See also the discussion of `"uS"` above.

plb_update - property listbox update:

- Synopsis: `"plb_update"`
- Description: Clear the current property GUI, ask the currently selected object for a list of properties and insert them in the property listbox, then rebuild the property GUI of the property with the same index in the property listbox as the property selected before plb_update was started (this is not necessarily a property of the same type).

Since Ayam 1.13 it is also possible to automatically run GUI updating commands in the console by using `<Shift+Return>` instead of `<Return>`. The commands from the hidden preference setting `"AUCommands"` will be executed after the commands from the command line, if the `<Shift>` key is held down. `<Shift+Return>` may also be used without commands on the command line. By default, the `"AUCommands"` are `"uS; rV;"`, leading to updated object tree, property GUI, and views.

### Custom Objects

This command manages custom objects (plugins):

io_lc - load custom:

- Synopsis: `"io_lc filename"`
- Description: Load the custom object (plugin) from file filename. Note that it is currently not possible to unload a custom object from Ayam.

### Applying Commands to a Number of Objects

There are two commands that help to apply arbitrary commands to a number of objects, forAll and forAllT:

forAll:

- Synopsis: `"forAll recursive command"`
- Description: The forAll command executes command for all objects that have been selected currently, or for every object of the current level if nothing has been selected. If recursive is 1 then forAll will recurse into every object (if it has child objects) before the execution of command. Note that forAll will run slowly if a property GUI is displayed. You can make it run faster by de-selecting the property using e.g. the property context menu first.
- Deficiencies:
  - A recursive forAll will e.g. also descend into NURBS patches (if they have trim curves) and apply the command to the trim curves, which might not exactly be what you want. Use `"forAllT"` in this case.
  - The command will not have access to global arrays unless e.g. one of the following construct is in use:

    `"forAll 0 { uplevel #0 { commands } }"`

    `"forAll 0 { global arrayname; commands }"`

  - It is not possible to use commands that change the object hierarchy (e.g. deleting or inserting objects). The commands may just modify existing objects. Since Ayam 1.9 `"forAll"` correctly maintains the current selection.

forAllT:

- Synopsis: `"forAllT type recursive command"`
- Description: forAllT works the same way as forAll, with an additional type check. The command will not be executed if the type of the current object does not match the argument type. Note that forAllT will run slowly if a property GUI is displayed. You can make it run faster by de-selecting the property using e.g. the property context menu first.

  Note that the type strings will be converted to lowercase before comparison, so that it is legal to use forAllT e.g. this way:

  `"forAllT ncurve 0 {puts $i}"`

- Deficiencies:
  - The command will not have access to global arrays unless e.g. one of the following constructs is in use:

    `"forAllT ncurve 0 {uplevel #0 {commands} }"`

    `"forAllT ncurve 0 { global arrayname; commands }"`

  - It is not possible to use commands that change the object hierarchy (e.g. deleting or inserting objects). The commands may just modify existing objects. Since Ayam 1.9 `"forAllT"` correctly maintains the current selection.

### Scene IO

These commands help to load scenes from and save them to Ayam scene files:

newScene:

- Synopsis: `"newScene"`
- Description: clears the current scene.

replaceScene:

- Synopsis: `"replaceScene filename"`
- Description: clears the current scene, then loads a new scene from filename.

insertScene:

- Synopsis: `"insertScene filename"`
- Description: inserts a scene from filename.

saveScene:

- Synopsis: `"saveScene filename"`
- Description: saves the current scene to filename.

### RIB Export

This command allows to export the current scene to a RenderMan Interface Bytestream (RIB):

wrib - RIB export:

- Synopsis: `"wrib -file filename [-image imagename] [-smonly|-selonly]"`
- Description: exports the current scene to a RIB file designated by `"filename"`. If the argument `"-image"` is given, the RIB file will create an image file named `"imagename"` upon rendering. The export will use the camera transformation from the currently selected Camera object. If the argument `"-smonly"` is provided, a RIB to render shadow maps will be created and the argument of `"-image"` will be ignored. If the argument `"-selonly"` is given, only the selected (geometric) objects will be exported, which will result in a RIB file not suitable for rendering (no setup, camera transformation, or lights are in it) but for inclusion into other scenes via RiArchive. The `"wrib"` command always needs a selected camera object; if there is none or if the camera transformations of the camera associated with a view window shall be used, the corresponding Togl callback for the view might be used like this instead:

      .view1.f3D.togl wrib -file filename.rib

  The Togl callback understands the same options as the `"wrib"` command.

### Reporting Errors

This command is for error reporting from scripts:

ayError:

- Synopsis: `"ayError code place detail"`
- Description: This command reports errors or warnings. You should always use ayError instead of puts because the error reporting mechanism of Ayam features compression of repeated messages and logging to files. Code should be one of: 1: warning, 2: error, 3: flush messages, 4: unspecified output. There are more codes defined (see ayam.h, look for Return/Error Codes) but they are not needed in the Tcl script context. Place should describe the procedure where the error occured. Detail is the string to be output.

### Miscellaneous

Miscellaneous commands:

getType:

- Synopsis: `"getType varname"`
- Description: This command writes the type of the selected object into the variable varname. The types are the well known strings that are displayed in the hierarchy list box if the objects are not named (NPatch, NCurve, Sphere, etc.).

tmpGet:

- Synopsis: `"tmpGet tmpdir varname"`
- Description: This command calculates a name for a temporary file in tmpdir and puts the complete name into varname.

hasChild:

- Synopsis: `"hasChild"`
- Description: This command returns 1 if the selected object has child objects, otherwise it returns 0.

undo:

- Synopsis: `"undo [redo|save opname [0|1]|clear|rewind]"`
- Description:
  - If called without arguments, this command performs the undo operation.
  - If the argument is `"redo"`, this command performs the redo operation.
  - If the argument is `"save"`, the currently selected objects are saved to the undo buffer for future undo operations. The name of the now following modelling operation has to be provided in a second argument (`"opname"`). This name will be displayed in the default console prompt, to inform the user about which operation would be undone/redone, if undo/redo would be used (e.g. `"[Undo:MoveObj/Redo:none].../bin>"`). Since Ayam 1.13, a third argument may be given, that controls, whether all the children of the selected objects should also be saved. This may be needed if the modelling action that follows the undo save is about to change the selected objects and also their children. Note: undo save does not fail if no objects are selected.
  - If the argument is `"clear"`, all currently saved states will be cleared from the undo buffer.
  - The argument `"rewind"` is available since Ayam 1.14. With this command you can undo the last undo save operation. This may be necessary, if a modelling operation failed. Care should be taken, however, to not rewind the undo state, when a modelling operation only failed for some (not for all) of the selected objects.
- Example:

      undo save "MovOb"
      set ay_error ""
      movOb 0 1 0
      if { $ay_error > 1 } {
        undo rewind
      }

See also section The Undo System.

convOb:

- Synopsis: `"convOb [-inplace]"`
- Description: This command calls the registered converter for the selected object(s). If the option `"-inplace"` is used, the new object(s) will replace the old object(s).

forceNot:

- Synopsis: `"forceNot [mod|all]"`
- Description: This command calls the registered notification callback for the selected object(s) and their parents, or, if no object is selected, for all objects of the scene. If the `"mod"` parameter is used, only modified objects will be notified. If the `"all"` parameter is used, all objects will be notified regardless of the selection.

addToProc:

- Synopsis: `"addToProc procedure addition"`
- Description: This command adds the code from addition to the procedure procedure.
- Note: This command uses the introspection facilities of Tcl and works only correctly for procedures, that end with a single `"return;"` statement.

## 6.3 Scripting Interface Examples

Here are some complete example scripts for the Ayam Tcl scripting interface.

You may copy and paste all examples directly from the documentation into the console of Ayam.

### Moving Objects

The following example script shows how to move a selected object to a specified position in space.

    proc placeOb { x y z } {
      global transfPropData

      # copy Transformations-property data to
      # global array "transfPropData"
      getTrafo

      # set array values according to procedure parameters
      set transfPropData(Translate_X) $x
      set transfPropData(Translate_Y) $y
      set transfPropData(Translate_Z) $z

      # copy Transformations-property data from
      # global array "transfPropData" to selected object
      setTrafo
    }
    # placeOb

In order to move all selected objects to 1 1 1 you may enter the following into the console:

    forAll 0 {placeOb 1 1 1}

But perhaps you would rather like a small GUI for that? No problem, the following snippet adds an entry to the custom menu that opens a small requester for the x-, y-, and z-values and calls the `"placeOb"` procedure (defined above) with them:

    global ay
    $ay(cm) add command -label "Place Object" -command {
     runTool {x y z} {"X:" "Y:" "Z:"} "forAll 0 {placeOb %0 %1 %2}"
     plb_update; rV
    }

The trailing `"plb_update; rV"` command ensures that the GUI is updated properly and all views display the new position of the moved objects.

### Moving NURBS points

The following example script snippet shows how to move control points of a NURBS curve.

    # first, we create a new NURBS curve with 30 control points
    set len 30
    crtOb NCurve -length $len
    # update selection
    uS
    # select last object (the newly created curve)
    sL
    # prepare moving
    set i 0
    set r 3.0
    set angle 0
    set angled [expr 3.14159265/2.0]
    while { $i < $len } {

        set x [expr $r*cos($angle)]
        set y [expr $r*sin($angle)]
        set z [expr $i/3.0]

        # move control point to new position
        setPnt $i $x $y $z 1.0

        set angle [expr $angle + $angled]
        incr i
    }
    # redraw all views
    rV

Now use this as path for a Sweep. For instance, using the next small script.

### Easy Sweep

The following example script shows how to easily create a sweep from a selected path curve (avoiding the manual and lengthy creation and parameterisation of a suitable cross section).

    proc easySweep { } {
     # first, we create a sweep object
     crtOb Sweep

     # now, we need to move the selected curve (path) to
     # the sweep and create a cross-section curve there too
     # for that, we move the currently selected curve to the clipboard
     cutOb
     uS

     # how does the current level look like?
     getLevel a b

     # enter the Sweep (the last object in the current level)
     goDown [expr [llength $a]-1]
     uS

     # now, we create a new curve (a closed B-Spline suitable as cross section)
     crtClosedBS 8
     uS

     # how does the current level look like?
     getLevel a b

     # select last object (the newly created curve)
     selOb [expr [llength $a]-1]

     # now, we rotate and scale the curve
     rotOb 0 90 0
     scalOb 0.25 0.25 1.0

     # move trajectory back (we use "cmovOb" and _not_ "pasOb", because we
     # really want to move (and not copy) the curve object
     cmovOb
     # go up to where we came from
     goUp

     # update GUI
     uS
     sL

     # redraw all views
     rV
    }
    # easySweep

Run this pocedure by selecting a NURBS curve object, then type into the console:

    easySweep

You may add this command to the main menu as well:

    global ay
    $ay(cm) add command -label "Easy Sweep" -command {
     easySweep
    }

After running the above script you should have a new menu entry `"Custom/Easy Sweep"` that calls the `easySweep` procedure.

### Toolbox Buttons

Here is another example script that shows how you may add buttons to the toolbox. myImage should be an image created e.g. from a GIF file of the size 25 by 25 pixels.

    global ay

    # create an image from a GIF file:
    image create photo myImage -format gif -file /home/user/giffile

    set b .tbw.f.mybutton

    # if the button not already exists:
    if { ![winfo exists $b] } {

      # create it:
      button $b -padx 0 -pady 0 -image myImage -command myCommand

      # tell Ayam about the new button:
      # you can use linsert, to insert the button in a specific
      # place or just append to the end of the list
      lappend ay(toolbuttons) mybutton

      # display the button:
      # from now on, it will be under the
      # automatic toolbox layout management
      toolbox_layout
    }

This example shows that a) buttons have to be created in the frame `".tbw.f"` b) Ayam manages a list of all buttons in the global array ay in `"ay(toolbuttons)"`, the order in that list is the order in which buttons appear in the toolbox c) automatic layout management is carried out by the procedure `"toolbox_layout"`.

Adding buttons with just text is a little bit more involved, as the sizes of the new buttons often do not fit well in the icon button scheme with its constant button size.

Here is an example that adds two buttons to the bottom of the toolbox spanning the whole window (this works best with the standard toolbox layout of 4 by 12 buttons):

    # create a frame:
    set f [frame .tbw.f.fcollex]

    # calculate the row number below the last row:
    set row [expr [lindex [grid size .tbw.f] 1] + 1]

    # now display the frame at calculated row, spanning the whole window:
    grid $f -row $row -column 0 -columnspan [lindex [grid size .tbw.f] 0]\
         -sticky we
    # create two buttons inside the frame:
    button $f.b1 -width 5 -text "Coll." -command { collMP; rV; }
    button $f.b2 -width 5 -text "Expl." -command { explMP; rV; }
    pack $f.b1 $f.b2 -side left -fill x -expand yes

## 6.4 Helper Scripts

This sections contains the documentation of some helper scripts that are distributed with Ayam.

All helper scripts may be run via the context menu of the console, the Tcl `"source"` command, or the `"Scripts"` preference setting of Ayam on each start.

### Repair Ayam

Since Ayam 1.8.2 an external Tcl script named `"repairAyam.tcl"` is provided that may be used to repair the application state of Ayam should it be stuck e.g. in an endless loop of Tcl error messages.

On Unix systems `"repairAyam"` may be started from any shell simply by typing `"./repairAyam.tcl"` or `"wish repairAyam.tcl"` (without the quotes) on the command prompt; if the script detects that it is running on Unix and not in Ayam it will send itself to the Tcl interpreter Ayam is running in using the Tk send command. On Mac OS X Aqua (not X11!) AppleScript events will be used instead of the Tk send command. If this does not work as expected `"repairAyam.tcl"` may still be run via the Ayam console (as on Win32).

On Win32 you have to start `"repairAyam.tcl"` from the Ayam console using the command: `"source scripts/repairAyam.tcl"` or using the consoles context menu: `"Console/Load File"`.

The script `"repairAyam.tcl"` should be considered a last resort to help you save your modified objects!

The script will close all views, clean up the application state variables, reset the mouse cursor and the console prompt, and try to update important main window widgets. Since Ayam 1.9 it will also clear the console and try to break potential endless loops running e.g. in the console or in script objects.

After running `"repairAyam.tcl"` you should immediately save the scene (or just the important objects you were editing, possibly using `"Special/Save Selected"`) to a new file, not the scene file you were working with initially, and restart Ayam.

### Convert Everything to Polygons

Since Ayam 1.13 there ist a script named `"topoly.tcl"` that recursively browses through the scene and converts everything to a polygonal representation.

After running the script, there is a new button in the toolbox named `"ToPolyMesh"`. Additionally, there is a corresponding entry in the `"Custom"` main menu. Pressing the button or using the menu entry immediately starts the conversion process.

Since the changes of the conversion are not undoable, the conversion will not run if the scene contains unsaved changes.

The conversion will use the parameters from the preference settings `"SMethod"`, `"SParamU"`, and `"SParamV"` or from `"TP"` tags (if present). TP tags may be created easily using the tesselation tool, see also section The Tesselation Tool.

### Restrict the Console

The script `"2lcons.tcl"` (for two line console), may be used to restrict the screen space occupied by the console.

Normally, the Ayam console is resized with the main window and occupies a varying amount of screen space. After running the script, the console will always resize to exactly two lines. Different values may be chosen easily by adapting the script.

### Access Core Functions from the Toolbox

The script `"zap.tcl"` demonstrates, how arbitrary core functionality that is just available through a main menu entry or the scripting interface might be accessed easily via the toolbox window.

After running the script `"zap.tcl"`, there will be a new toolbox button, labeled `"Zap!"`, that simply runs the zap command (which iconifies the complete application).

Next Previous Contents