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

Note that most of the listed commands work in background, without changing anything to the Ayam GUI and Ayam view windows, for execution speed. If you want your changes to become visible you have to update the various parts of the GUI explicitly (see also section Updating the GUI).

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.

6.1 Global Variables

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

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". Use "parray ayprefs" in the console to see what is there. More documentation to come.

More documentation to come.

6.2 Index of Procedures and Commands

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

Creating Objects

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

Manipulating the Selection

This command is probably the most important one, because a lot of the other commands operate on selected objects only.

selOb - select object(s):

withOb - work on certain selected object(s):

Manipulating Properties

Every property has a corresponding global array, 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 named like the property itself, e.g. for the tags property the following global array is defined:


array set Tags {
arr   tagsPropData
sproc setTagsp
gproc getTagsp
w     fTagsAttr
}

If sproc or gproc are empty (""), a standard callback named "setProp" or "getProp" should be used.

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

Clipboard Operations

These commands operate the object clipboard:

copOb - copy object:

cutOb - cut object:

pasOb - paste object:

delOb - delete object:

cmovOb - paste (move) object:

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

pclip_paste/pasteProp - paste a property

Hierarchy Operations

These commands manipulate the current level of Ayam.

goDown:

goUp:

goTop:

Transformations

movOb - move objects:

rotOb - rotate objects:

scalOb - scale objects:

movSel - move selected points:

rotSel - rotate selected points:

scalSel - scale selected points:

delegTrafo - delegate transformations:

applyTrafo - apply transformations:

Manipulating Shaders

shaderSet:

shaderGet:

Manipulating Tags

addTag:

delTags:

getTags:

setTags:

Manipulating NURBS Curves and Surfaces

clampNC - clamp NURBS curve:

elevateNC - elevate NURBS curve:

insknNC - insert knot into NURBS curve:

refineNC - refine NURBS curve:

revertNC - revert NURBS curve:

rescaleKnNC - rescale knots of NURBS curve:

splitNP - split NURBS patch:

buildNP - build NURBS patch:

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 object, e.g. a NURBS curve requires just one index parameter (indexu), whereas a NURBS patch requires two (indexu and indexv).

getPnt:

setPnt:

Updating the GUI

rV - redraw all views:

uS - update select:

uCL - update current level:

uCR - update current level after create:

plb_update - property listbox update:

Custom Objects

io_lc - load custom:

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:

forAllT:

Scene IO

newScene:

replaceScene:

insertScene:

saveScene:

Reporting Errors

ayError:

Miscellaneous

getType:

tmpGet:

hasChild:

undo:

convOb:

forceNot:

6.3 Scripting Interface Examples

Here are some 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}"
 uS
}

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 BSpline 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 move (and not copy) the curve
 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.

Tool Box Buttons

Here is another example that shows how you may add buttons to the tool box. 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/a.gif

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 tool box 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 tool box 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 tool box spanning the whole window (this works best with the standard tool box layout of 4 by 12 buttons):


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

# create two buttons inside the frame:
button $f.b1 -width 5 -text "Coll." -command { collNC; rV; }
button $f.b2 -width 5 -text "Expl." -command { explNC; rV; }
pack $f.b1 $f.b2 -side left -fill x -expand yes

# 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]


Next Previous Contents