Script Objects
A script object works like other drawing objects, but the geometry is created from a Python script.
Machining operations can be based on script objects in the same way as static drawing objects. They can also be moved, rotated and copied. Any changes made by the script will be automatically picked up by associated machining operations.
Scripts can be useful for generating parametric shapes (such as a gear, or tabbed box), creating copies of, or manipulating other drawing objects. Script objects can also be used to provide general functionality such as an animation.
Drawing scripts will typically create primitive shapes and add them to the Entities collection property using:
this.Entities.Add(...)
The following example draws an N-sided shape of a given radius.
# variable that define the shape...
n = 7
radius = 10
# create a polyline object...
poly = Polyline()
poly.Closed = True
for i in range(0,n):
th = i*2*Math.PI/n
poly.Add( radius * Math.Cos(th), radius * Math.Sin(th), 0)
# add the polyline to the list of drawing objects...
this.Entities.Add(poly)
# multiple drawing objects can be added...
this.Entities.Add(Circle(0,0,radius))
Resulting in this…
Script objects will usually run when required to update geometry, but can be forced to run by selecting them in the drawing tree and pressing F5.
Use Edit - Explode to turn script objects into their component static drawing objects, which can be used with previous CamBam versions or further manipulated using CamBam CAD operations.
When a script object is inserted using the Draw - Script object command, or by clicking the script toolbar icon , a default script is inserted. The contents of this script can be set in the Default Script Entity system configuration property.
Properties
|
The script text to be executed. The text can be edited by clicking the [...] button to the right of the property, or by double clicking any drawing objects that are created by the script. |
|
If True, the script will be executed automatically when required, such as when the drawing loads or if the script is modified. If False the script must be run manually by selecting the object and pressing F5. This can be useful for non-drawing scripts such as animations that only need to be run on demand. |
|
The Entities property contains a list of drawing objects that are generated by the script. |
|
A general purpose, multi-line text field that can be used to store notes or parameter data. |
|
A 4 x 4 matrix of numbers used for general transformations of the drawing objects. The transform matrix can be used for rotations, translations and scaling about all 3 axis. |
Copying drawing objects
Making copies of other drawing objects is a simple but powerful technique to allow easily managed drawings. Entities can be copied by looking for their ID, adding objects from a specific layer or including them from external drawings.
The following example makes 4 copies of a source object with each copy offset 18mm along the X axis.
This is much like using the Transform - Array Copy function with the benefit that any changes to the source object will be automatically reflected in the copies the next time the script is run by pressing F5.
# find drawing object with ID=7
ent = doc.FindPrimitive(7)
for i in range(1,5):
clone = ent.Clone()
clone.Transform.Translate(i*18,0,0)
this.Entities.Add(clone)
Using Layers
Hard coding source object IDs in scripts can be error prone. If the source object IDs change, any referring scripts will fail.
An alternative is to copy objects from a source Layer specified by name.
for ent in doc.Layers["Border"].Entities:
this.Entities.Add(ent.Clone())
Copying from external files
cbfile = CADFile()
filename = "samples\\skull-big-foam.cb"
cbfile.Open(FileUtils.GetFullPath(CamBamConfig.Defaults.SystemPath,filename))
for ent in cbfile.Layers["Default"].Entities:
this.Entities.Add(ent.Clone())
Including scripts
The script object includes scripts from the Script property of the parent layer, as well as the Script property at the top level of the drawing file. This allows functions, classes or variables to be defined once in the drawing, then referenced in any number of drawing objects.
CamBam inserts an internally generated header block before each script is run, to import commonly used name spaces. This helps keep the user scripts succinct. The internal header contains the following code.
import clr
clr.AddReference('System')
from System import *
clr.AddReference('System.Drawing')
from System.Drawing import *
from CamBam import *
from CamBam.CAD import *
from CamBam.CAM import *
from CamBam.UI import CamBamUI
from CamBam.Geom import *
When the script is run, the script components are appended together, so the actual script executed is given by:
Header + Drawing.Script + Layer.Script + ScriptEntity.Script
Importing external scripts and modules
Scripts can also be imported from external sources using the standard Python import instruction. This provides a way of managing a common library of drawing objects and other functions which can be shared throughout multiple drawings. Any changes to modules will be automatically picked up whenever scripts that refer to them are run.
This example will import the Pulleys.py module from the common scripts folder.
# import the module
import Pulleys
# declare a timing pulley object with pitch=5mm and 18 teeth
HTD5_18 = Pulleys.HTDPulley(5.0,18)
# add the pulley outline to the script object's drawing entities
this.Entities.Add(HTD5_18.getFrontView())
The import Pulleys
line instructs Python to search for a module called ‘Pulleys’.
Python will look in a search path including the current drawing’s folder and the CamBam system \ scripts folder.
There is a script in the CamBam system\script folder called Pulleys.py so that module is found and imported. CamBam also provides the following modules: Pulleys.py, StepperMotors.py and Bearings.py. The C-BEAM-Belt-Drive.cb sample file makes use of these modules to generate drawing objects.
Modules are imported in their own name-space, any names used from the module need to be prefixed with the module name, such as ‘Pulleys.HTDPully’. It is also possible to import module names into the current scripts name-space using a line like:
import Pulleys
# import just the HTDPulley name
from Pulleys import HTDPulley
# or import all names from the Pulleys module
from Pulleys import *
Then names like ‘HTDPulley’ can be used without the ‘Pulleys’ prefix.
Script modules are pretty much like any other script, except they need to be ‘self contained’. The internally generated header block described above will not be automatically added, so all required modules and name-spaces need to be imported into the module.
The module search path can be defined within the script to allow importing standard Python modules.
# append the module search path
import sys
sys.path.append("C:/Python27/Lib")
# import the Python CSV handling module
import csv
reader = csv.reader(open("C:/devt/test.csv", 'rb'))
for row in reader:
print str(row)
Animations
Scripts can be used to animate drawing objects by applying transformations such as rotations and translations then updating each frame within a loop. It is possible to rotate, scale and pan the drawing during the animation.
Animation scripts should be marked with Execute On Update set False, otherwise they will be run as soon as the file is loaded.
The script should also set the Animating property of the current view when the animation starts, then clear it at the end of the script. This allows the view to provide some optimizations as well as preventing non-selected objects to be displayed faded during the animation.
The script should also preserve the original transformation state of any objects being animated, then restore the transforms at the end of the script, otherwise the drawing will be left in a state with the source objects transformed as at the last animation frame.
The following example will rotate and translate an object with ID=1 along the X axis.
# find drawing object with ID=1
ent = doc.FindPrimitive(1)
# save the current transformation
tsave = ent.Transform
# start animating
view.Animating = 1
cycles = 4
for f in range(0,cycles*360):
# apply transformations to the source object
trans_translate = Matrix4x4F.Translation(f*0.1,0,0)
trans_rotate = Matrix4x4F.RotationZ(-f/180.0*Math.PI)
ent.Transform = tsave * trans_rotate * trans_translate
# update the display
view.RefreshView()
app.Sleep(5)
# restore the original transformation
ent.Transform = tsave
view.Animating = 0