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.
Several global variables exist in the Ayam Tcl context, that may be useful for scripts.
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"
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.
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):
"help command"
To create new objects the "crtOb"
command can be used.
"crtOb type [args]"
"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, other types expect 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.This command is probably the most important one, because a lot of the other commands operate on selected objects only.
"selOb [index]"
withOb - work on certain selected object(s):
"withOb index command"
Since Ayam 1.9 two new commands are implemented that ease the manipulation of property values:
getProperty - get single property value
"getProperty propname(elemname) varname"
"r"
easily using the command
"getProperty SphereAttr(Radius) r"
setProperty - set single property value
"setProperty propname(elemname) value"
"3.0"
easily using the command
"setProperty SphereAttr(Radius) 3.0"
Direct (fast) access of property values:
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 }
""
), a standard callback
named "setProp"
or "getProp"
should be used to get
or set the property values.
The following global arrays and callbacks to get or set the data exist:
These commands operate the object clipboard:
"copOb"
"cutOb"
"pasOb"
"delOb"
"cmovOb"
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_copy mode"
"copyProp"
.pclip_paste/pasteProp - paste a property
"pclip_paste"
"pasteProp"
.These commands manipulate the current level of Ayam.
"goDown index"
"goUp"
"goTop"
"movOb dx dy dz"
"rotOb dx dy dz"
"scalOb dx dy dz"
movSel - move selected points:
"movSel dx dy dz"
rotSel - rotate selected points:
"rotSel dx dy dz"
scalSel - scale selected points:
"scalSel dx dy dz"
delegTrafo - delegate transformations:
"delegTrafo"
applyTrafo - apply transformations:
"applyTrafo sel|all"
"shaderSet shadertype [varname]"
"surface"
, "displacement"
,
"light"
, "imager"
, "atmosphere"
, "exterior"
or "interior"
. If varname is not given, the shader in question
is deleted from the object instead."shaderGet shadertype varname"
"surface"
, "displacement"
,
"light"
, "imager"
, "atmosphere"
, "exterior"
or "interior"
. The shader will be written to an array
pointed to by varname."addTag type value"
""
as value parameter. This is e.g.
needed for the "NoExport"
tag."delTags type"
"all"
, all tags are deleted from the
currently selected objects(s)."getTags tvname vvname"
"setTags tags"
"clampNC"
"Custom"
and
the knots will have o equal values at start and end (where o is the
order of the curve).elevateNC - elevate NURBS curve:
"elevateNC n"
"Custom"
.insknNC - insert knot into NURBS curve:
"insknNC u r"
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!refineNC - refine NURBS curve:
"refineNC [{u1 u2 un}]"
"Custom"
.revertNC - revert NURBS curve:
"revertNC"
rescaleKnNC - rescale knots of NURBS curve:
"rescaleKnNC [-r rmin rmax|-d mindist]"
[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."splitNP (u|v)"
"buildNPatch"
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 [-trafo] indexu [indexv] varx vary varz [varw]"
"-trafo"
is given, the coordinates
will be transformed by the values given in the objects
Transformation property."setPnt indexu [indexv] x y z [w]"
rV - redraw all views:
"rV"
"uS [update_prop maintain_selection]"
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.
"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;
"uCR"
may be used instead of "uS"
."uCL cl"
may be used instead of "uS"
."uCL mode [args]"
"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:
"uCR"
"uS"
above.plb_update - property listbox update:
"plb_update"
io_lc - load custom:
"io_lc filename"
There are two commands that help to apply arbitrary commands to a number of objects, forAll and forAllT.
"forAll recursive command"
"forAllT"
in this case."forAll 0 { uplevel #0 { commands } }"
"forAll 0 { global arrayname; commands }"
"forAll"
correctly maintains the current selection."forAllT type recursive command"
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}"
"forAllT ncurve 0 {uplevel #0 {commands} }"
"forAllT ncurve 0 { global arrayname; commands }"
"forAllT"
correctly maintains the current selection.newScene:
"newScene"
"replaceScene filename"
"insertScene filename"
"saveScene filename"
"wrib -file filename [-image imagename] [-smonly|-selonly]"
"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. To use the camera transformations of the camera associated
with a view window use the corresponding Togl callback for the view
like this instead: .view1.f3D.togl wrib -file filename.rib
.
If the argument "-smonly"
is provided, a RIB to render shadow maps
will be created and the argument 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."ayError code place detail"
getType:
"getType varname"
"tmpGet tmpdir varname"
"hasChild"
"undo [redo|save opname|clear]"
"redo"
, this command performs the redo
operation."save"
, the currently selected objects
are saved to the undo buffer for future undo operations. The name
of the following operation has to be provided in a second argument.
It 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."clear"
, the undo buffer is cleared."convOb [-inplace]"
"-inplace"
is
used the new object(s) will replace the old object(s)."forceNot"
"addToProc procedure addition"
"return;"
statement.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.
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
forAll 0 {placeOb 1 1 1}
"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 }
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
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 }
Custom/Easy Sweep
that calls the easySweep
procedure.
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] # 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