Simple user-created scripts can be used to extend K-3D at runtime in an amazing variety of ways:
- Scripts can be run from the command-line to peform "batch" processing.
- Scripts can be run from within the graphical user interface to automate repetitive tasks.
- Special scripted plugins can be used to provide scripted data sources, data modifiers, and data sinks that function as part of the Visualization Pipeline.
- Scripts can be integrated with K-3D's plugin system so that they are indistinguishable from compiled C++ plugins within the user interface.
- Scripts can be run automatically when K-3D starts and when it shuts-down.
- Scripts can be run automatically when a document is created and when it closed.
- Scripts are used for most of the regression tests in the K-3D Dashboard.
In K-3D, scripting engines are another type of plugin, so K-3D is capable of using any scripting language for which a plugin has been written. Currently there is one scripting engine plugin included with K-3D:
- Python - The preferred script engine for all new development, combining the power and flexibility of the Python language and libraries with K-3D.
At the Command-Line
You can run scripts from the command-line when starting K-3D, using the --script option:
$ k3d --script=my_script.py
When running scripts in this fashion you will often want to exit the program once the script has completed. To do so, use the --exit option:
$ k3d --script=my_script.py --exit
It is also typical to run K-3D as a strictly command-line application in this case, so you can perform batch processing on a headless server. Because user interfaces are a type of plugin in K-3D, it's easy to substitute the NUI (Null User Interface) plugin, which will consume fewer resources, startup faster, and avoid "flashing" windows as the program quickly runs and exits:
$ k3d --script-my_script.py --ui=none --exit
You can use the --script option multiple times, to run more-than-one script in-order:
$ k3d --script=first_script.py --script=second_script.py --ui=none --exit
Use a dash ("-") as the script name to read the script source from stdin, allowing you to dynamically-generate scripts and pipe them into K-3D:
$ script_generator | k3d --script=- --ui=none --exit
You can combine scripting with the other command-line options such as --open, which you could use to open a K-3D file before running the script. For example you might create a "template" scene for rendering, then run a script that modifies the template, renders, then exits:
$ k3d --open=template_scene.k3d --script=modify_template.py --ui=none --exit
See Command Line Options for other useful options you can use with scripting.
From the User Interface
To run a script from K-3D user interface, choose Scripting > Play - you will be prompted for the filename of the script to be run.
K-3D provides a wide variety of scripted nodes that allow scripts to become data sources, data modifiers, and data consumers within the Visualization Pipeline. To use these nodes, you simply create an instance of the node and modify its "Script" property to implement the desired behavior. The node's inputs and outputs can be connected with the rest of the Visualization Pipeline in the normal way, and your script will be executed whenever the node needs to refresh its outputs. See Category:Scripting for a list of scripted node types.
Scripts can be loaded by K-3D at startup and integrated into the plugin system so that - from the perspective of the end user - they are indistinguishable from "normal" C++ document plugins. To do this, script authors simply embed a few lines of plugin-related metadata into their script, and place the script in a known-location where it will be loaded by K-3D at startup.
The required plugin metadata is composed of name-value pairs that follow the syntax of an XML attribute and are embedded into the script source using whichever comment syntax is appropriate to the scripting language. See Plugin Metadata for a detailed description of allowed metadata. As an example, the following lines define the beginning of a script that will appear as "MyCoffeeMugMeshSource" in the Create > Scripts menu, and will be executed by a MeshSourceScript plugin when selected by the user.
#python # k3d:plugin-class="document" # k3d:plugin-type="MeshSourceScript" # k3d:plugin-name="MyCoffeeMugMeshSource" # k3d:plugin-description="Creates a polygonal mesh shaped like a coffee mug" ...
Once the metadata is in place, the script can be put in one of two locations, and it will be automatically loaded when K-3D starts:
Once loaded, the script will appear in the Create > Scripts menu as a normal item that the user can click to create.
In addition to scripted document plugins that are created by the user and become part of a document, you can create "action" scripts that simply run and exit when selected. The following complete example will appear in the Scripting > Actions menu and creates a QuadricCone when run:
#python # k3d:plugin-class="application" # k3d:plugin-type="ActionScript" # k3d:plugin-name="Create Cone" # ngui:action="" import k3d # Create a cone primitive source cone = k3d.plugin.create("QuadricCone", context.document) cone.height = 1 cone.radius = 0.5 # Create a mesh instance that will place the cone primitive into the scene mesh_instance = k3d.plugin.create("MeshInstance", context.document) # Specify OpenGL and RenderMan painters for rendering the cone primitive mesh_instance.gl_painter = k3d.node.lookup_one(context.document, "GL Default Painter") mesh_instance.ri_painter = k3d.node.lookup_one(context.document, "RenderMan Default Painter") # Connect the cone source to the mesh instance k3d.property.connect(context.document, cone.get_property("output_mesh"), mesh_instance.get_property("input_mesh")) # Ensure that the mesh instance will be visible for every render engine in the scene k3d.node.show(context.document, mesh_instance)
You can also designate plugin scripts as "auto-start" scripts that will be automatically-run in response to certain events. Currently there are several categories of event, which are described in greater detail under Plugin Metadata:
Here is an example of an auto-start plugin that writes to a log file when the program is run:
#python # k3d:plugin-class="application" # k3d:plugin-type="ActionScript" # k3d:plugin-name="ApplicationLog" # k3d:application-start="" from datetime import datetime log = open("k3d.usage_log", "a") if context.command == "startup": log.write("K-3D started at " + str(datetime.now()) + "\n") elif context.command == "shutdown": log.write("K-3D closed at " + str(datetime.now()) + "\n")
Similarly, here is an example that displays time spent working with a document whenever the document is closed (but only if the normal graphical user interface is in use):
#python # k3d:plugin-class="application" # k3d:plugin-type="ActionScript" # k3d:plugin-name="DisplayBillingTime" # ngui:document-start="" import k3d from datetime import datetime if context.command == "startup": start_time = datetime.now() elif context.command == "shutdown": elapsed = datetime.now() - start_time k3d.ui().message("You worked on this document for " + str(elapsed.days) + " days, " + str(elapsed.seconds) + " seconds")
A variety of sample scripts are included with K-3D in the share directory:
- k3d/share/scripts - Contains scripts that can be run "standalone" from the graphical user interface using the Scripting > Play menu item.
- k3d/share/scripts/MeshModifierScript - Contains scripts designed for use with the MeshModifierScript plugin.
- k3d/share/scripts/MeshSourceScript - Contains scripts designed for use with the MeshSourceScript plugin.
- k3d/share/scripts/RenderManScript - Contains scripts designed for use with the RenderManScript plugin, which can "inject" custom RenderMan API calls into a rendered scene under script control.
- New in K-3D 0.7! k3d/share/scripts/MeshPainterScript - Contains scripts designed for use with the MeshPainterScript plugin, which can draw in the viewport under script control.
- New in K-3D 0.7! k3d/share/scripts/RenderEngineScript - Contains scripts designed for use with the RenderEngineScript plugin, which can integrate with external render engines under script control.
- New in K-3D 0.7! k3d/share/scripts/scripted_plugins - Contains scripts that are automatically integrated into the rest of the user interface as if they were "normal" C++ plugins.