DarkRadiant Script Reference

From The DarkMod Wiki
Jump to navigationJump to search

DarkRadiant is offering a Python script interface which provides access to the most important functions, such as the Virtual File System, the Shader System and the Scenegraph. A complete reference of all available classes can be found later in this article.

If you just want to run the scripts, see here: Running Scripts in Darkradiant.

Entering Script Code

Script code can be brought to execution by either entering it in the ad-hoc scripting window (in the group dialog) or by saving it in a .py file in the install/scripts/ folder and running it by entering the command "RunScript yourfile.py" in the command console. Python files are loaded and interpreted each time the runscript command occurs, so it's easy to tweak your code and test it in DarkRadiant right after you hit the save button.

There is a test.py in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.

The 'darkradiant' Module

All DarkRadiant classes and types are in the darkradiant module which can be imported like this

import darkradiant as dr

One can of course omit the as dr alias, but it's less typing this way. All the "Global*" objects like GlobalShaderSystem (see below) are already exposed to this scripts. The rest needs to imported from the darkradiant module and referred to by the prefix "dr".

Classes and Methods

DarkRadiant's "internal C++ code is organised into various modules. Each module provides a set of functions, for instance: the GlobalMaterialManager object provides methods to acquire information about all available shaders; the GlobalBrushCreator can be called whenever a new brush should be instanced. The script interface is following the same route and exposes most of these modules to scripting. The following should give you an overview of all the module objects available for your scripts. Examples are given whenever possible.

GlobalSceneGraph

When a map is loaded, the SceneGraph is populated with so-called SceneNodes. Each node represents an object in the map, be it a brush, a patch, an entity or a model (technically, a model is attached as child to a single entity). Each scenegraph has one single root, which can be access through the GlobalSceneGraph module.

  • SceneNode root() Returns the reference to the root node of the global scenegraph. This can return an empty "NULL" node if no map is loaded at invocation time.

SceneNode

A SceneNode provides a set of methods to gain information about its type, its position, etc. A SceneNode is a general object, its actual type can be BrushNode, PatchNode, EntityNode or ModelNode. Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. The methods of a general SceneNode are as follows:

  • isNull() Returns true if this node is "empty", i.e. it is the NULL node. Calling methods on a NULL node doesn't have any effect.
  • addToContainer(SceneNode newContainer) Adds this node as child to the given container.
  • removeFromParent() Removes this node from any parent container. If this node has no parent, nothing happens.
  • AABB getWorldAABB() Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.
  • SceneNode getParent() Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.
  • string getNodeType() Returns the type string of this node. Possible values: "map", "entity", "primitive", "unknown"
  • traverse(SceneNodeVisitor visitor) Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.
  • traverseChildren(SceneNodeVisitor visitor) Traverses all the children of this node using the given Visitor object. See the tutorial about scenegraph traversal for more information. (since 1.8.1)
  • setSelected(bool isSelected) Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).
  • invertSelected() Inverts the selection status of this node, i.e. if it is selected before this call, it will be deselected. Not all nodes are selectable.
  • bool isSelected() Returns the selection status of this node. A return value true means that this node is selected.

SceneGraph Traversal

It's possible to iterate over a given node's children which happens in a distinct way. In order to do that, a "SceneNodeVisitor" object is needed which is (as the name states) "visiting" each node along the route.

A node traversal works like this: first, the node itself is visited (depth 0), then all its children (depth 1). At each node the visitor will visit all the children first, before it continues to visit the "sibling" nodes.

This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):

# This is the visitor object
class SceneWalker(SceneNodeVisitor) :
 	def pre(self, node):
		# Print the type string of each visited node
		print(node.getNodeType())
		return 1

# Instantiate a new walker object
walker = SceneWalker()
GlobalSceneGraph.root().traverse(walker)

Let's say we have a simple scenegraph containing a root node. The root node has two entity nodes as children. The first entity (which is usually the worldspawn) is parent of two brush nodes, the second entity has no children (could be a light). When this scenegraph is traversed (starting from the root), the visitor will produce the following output:

entity
primitive
primitive
entity

Looking closely at this route, it is obvious that Entity 1's children are traversed before Entity 2, which is important. The visitor will always try to gain more "depth" before continuing to traverse on the same depth. It is possible to prevent traversal of a node's children: the visitor just needs to return false (0) when visiting a certain node. Let's say you don't want to traverse the worldspawn brushes, because you're interested in entities only:

# This visitor will NOT traverse children of entities
class EntityWalker(SceneNodeVisitor) :
 	def pre(self, node):
		# Check whether we have an entity
		if node.isEntity():
			# ...
			# do something with this entity
			# ...
			return 0 # return false: don't traverse entities
		else:
			return 1 # not an entity, return true to traverse children

# Instantiate a new entity walker object
walker = EntityWalker()
GlobalSceneGraph.root().traverse(walker)

The output will be something like this:

entity
entity

You might wonder why the visit function is called pre. There is indeed a post function, which can be added to the visitor object, optionally. When the post function is defined, it will be invoked after the walker has finished traversing a node's children. This is an example:

# This visitor has both pre and post functions defined
class SceneWalker(SceneNodeVisitor) :
	def pre(self, node):
		# Print the type string of each visited node
		print('Pre: ' + node.getNodeType())
		return 1
	def post(self, node):
		# Print the type string of each visited node
		print('Post: ' + node.getNodeType())

# Instantiate a new walker object
walker = SceneWalker()
GlobalSceneGraph.root().traverse(walker)

Using this walker, the output will be something like this:

Pre: entity
Pre: primitive
Post: primitive
Pre: primitive
Post: primitive
Post: entity
Pre: entity
Post: entity

As obvious, the visitor visited the first entity (pre), then its children are traversed, and finally the entity is visited once more (post), before the walker proceeds to the next entity. Note: the post method doesn't need to return anything, unlike the pre method. Most of the time you don't need to define a post method, but it might prove to be useful sometimes.

Special SceneNode Types

A SceneNode is just a general object. For some purposes it might be enough to have a SceneNode in your hands, but sometimes you'll want to know the actual node type, whether it is a brush, a patch, an entity or a model. Each SceneNode has a couple of is*() and get*() methods, like isBrush() and getBrush(). You can use the is*() methods to check whether a node is of a specific type, and the get*() methods to convert a SceneNode to a special node type. An example:

if node.isBrush():
	print('Node is a brush!')
else:
	print('Node is not a brush.')

If you want actually do something with a brush, more than just confirming its type, you'll want to go with this code:

brush = node.getBrush()
if not brush.isNull():
	# We've successfully converted the SceneNode into a BrushNode
	print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')
else:
	print('Node is not a brush')

The above code attempts to convert an existing node to a BrushNode. This will succeed only if the node is actually of the correct type, otherwise a NULL node will be returned, which is what the code above checks. If the brush object is not the NULL node, the cast succeeded and we have a valid brushnode in our hands.

There exist analogous methods for entities, models and patches, they are called:

  • isEntity()
  • EntityNode getEntity()
  • isPatch()
  • PatchNode getPatch()
  • isModel()
  • ModelNode getModel()

Each node type provides some special methods, additionally to the ones that come with a SceneNode. A BrushNode has all the methods of a SceneNode, plus a few more.

BrushNode

  • int getNumFaces() Returns the number of faces of this brush.
  • Face getFace(int faceIndex) Returns the face with the given index (see below for further description about a Face).
  • bool empty() returns true (1) if this brush has no faces.
  • bool hasContributingFaces() Returns true (1) if this brush has contributing (non-degenerate) faces.
  • removeEmptyFaces() removes degenerate faces.
  • setShader(string newShader) Sets the shader of all faces of this brush.
  • bool hasShader(string shaderName) Returns true (1) if one or more faces of this brush carries the given shader.
  • bool hasVisibleMaterial() Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).
  • undoSave() Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.
  • getDetailFlag() Returns the detail/structural flag for this brush (Values: BrushDetailFlag.Detail and BrushDetailFlag.Structural). (since 1.8.1)
  • setDetailFlag(BrushDetailFlag) Sets the detail/structural flag for this brush (Values: BrushDetailFlag.Detail and BrushDetailFlag.Structural) (since 1.8.1).
Face
  • undoSave() Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.
  • setShader(string newShader) Sets the shader of this face.
  • string getShader() Returns the shader name of this face.
  • shiftTexdef(s,t) shifts the texture of this face by s,t in texture space.
  • scaleTexdef(s_scale, t_scale) scales the tex def by the given factors in texture space.
  • rotateTexdef(float angle) rotates the texture by the given angle.
  • fitTexture(s_repeat, t_repeat) fits the texture to this face, so that it repeats the given amount of times.
  • flipTexture(int axis) flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)
  • normaliseTexture() This translates the texture as much towards the origin in texture space as possible without changing the world appearance.
  • Winding getWinding() Get read access to this Face's Winding object (see below).
Winding

A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type WindingVertex. The WindingVertex members are as below, read-only:

  • Vector3 vertex the 3D coordinates of the point
  • Vector2 texcoord the UV coordinates
  • Vector3 tangent the tangent
  • Vector3 bitangent the bitangent
  • Vector3 normal the normal vector
  • unsigned adjacent the index of the adjacent WindingVertex

PatchNode

  • setDims(unsigned width, unsigned height) sets the new patch dimensions.
  • int getWidth() returns the patch width (number of columns), returns -1 if the object is not a patch.
  • int getHeight() returns the patch height (number of rows), returns -1 if the object is not a patch.
  • PatchControl ctrlAt(unsigned row, unsigned col) returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.
  • string getShader() Returns the shader name for this patch.
  • setShader(string newShaderName) Sets the shader name for this patch.
  • bool hasVisibleMaterial() returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).
  • insertColumns(unsigned colIndex) Inserts two columns before and after the column with index <colIndex>.
  • insertRows(unsigned rowIndex) Inserts two rows before and after the row with index <rowIndex>.
  • removePoints(bool columns, unsigned index) Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.
  • appendPoints(bool columns, bool beginning) Appends two rows or columns at the beginning or the end.
  • bool isValid() Check if the patch has invalid control points or width/height are zero
  • bool isDegenerate() Check whether all control vertices are in the same 3D spot (with minimal tolerance)
  • bool subdivionsFixed() Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there
  • bool subdivisionsFixed() Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)
  • Subdivisions getSubdivisions() Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value
  • setFixedSubdivisions(bool isFixed, Subdivisions divisions) Sets the subdivision of this patch: isFixed: TRUE, if this patch should be a patchDef3 (fixed tesselation), divisions: a two-component vector containing the desired subdivisions.
  • controlPointsChanged() Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.
  • PatchMesh getTesselatedPatchMesh() Returns a (read-only) structure containing information about the current patch geometry, fully tesselated. The structure PatchMesh holds width, height and vertex information (see below).
PatchMesh

The PatchMesh holds an array of Vertex info objects, the number of which is depending on the amount of subdivisions of the patch. Members are:

  • width the width of the tesselated matrix.
  • height the height of the tesselated matrix.
  • vertices an enumerable structure containing all the vertices of the patch. Each element is of type PatchMeshVertex (see below). Changing the vertices will not affect the patch, this information is just a copy of the actual data. The vertex at w,h can be directly accessed using vertices[h*width + w].
PatchMeshVertex

A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:

  • Vector3 vertex the 3D point of this vertex.
  • Vector2 texcoord the UV coordinates.
  • Vector3 normal the normal vector.
PatchControl

A PatchControl is a structure containing information about a patch vertex. It has the following members:

  • vertex This is a vector holding the 3D coordinates of this control point, see Vector3.
  • texcoord This is a vector holding the 2D texture coordinates of this control point, see Vector2.
Subdivisions

This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.

  • x The number of horizontal subdivisions, e.g. patch.getSubdivisions().x()
  • y The number of vertical subdivisions, e.g. patch.getSubdivisions().y()

EntityNode

  • string getKeyValue(string key) Returns the value of the given entity key (=spawnarg).
  • setKeyValue(string key, string value) Sets the value of the named key, i.e. setKeyValue('health', '100').
  • forEachKeyValue(EntityVisitor visitor) Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).
  • bool isModel() Returns true if this entity is a model.
  • bool isOfType(string className) Returns true if this entity is of type or inherits from the given entity class name. className is treated case-sensitively (new in 1.8.1).
  • bool isInherited(string key) Returns true (1) when the given key is an inherited one.
  • EntityClass getEntityClass() Returns the reference to the EntityClass (the object representing the entityDef) of this entity.
  • EntityKeyValuePairs getKeyValuePairs(string prefix) Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.
EntityVisitor

An EntityVisitor object can be used to traverse the list of spawnargs on a given entity. Such an object just needs to implement a single visit function, see this example:

# This is the prototype of an EntityVisitor object
class MyEntityVisitor(EntityVisitor) :
	def visit(self, key, value):
		print('Worldspawn has spawnarg: ' + key + ' = ' + value)

worldspawn = GlobalMap.getWorldSpawn()
if not worldspawn.isNull():
	ev = MyEntityVisitor()

	# Cast the node onto an entity
	worldspawnent = worldspawn.getEntity()

	worldspawnent.forEachKeyValue(ev)

ModelNode

ModelNodes provide access to the model geometry and shaders, e.g. a chest model of a specific entity. ModelNodes are usually encountered as child of an EntityNode. ModelNodes cannot have any child nodes.

  • string getFilename() Returns the filename (without path) of this model.
  • string getModelPath() Returns the VFS path which can be used to load this model from the modelcache.
  • int getSurfaceCount() Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.
  • int getVertexCount() Return the number of vertices in this model, equal to the sum of the vertex count from each surface.
  • int getPolyCount() Return the number of triangles in this model, equal to the sum of the triangle count from each surface.
  • MaterialList getActiveMaterials() Return a vector of strings listing the active materials used in this model, after any skin remaps. The list is owned by the model instance.
  • ModelSurface getSurface(int surfaceIndex) Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)
ModelSurface

A ModelSurface represents a single mesh, which is part of a model. Each ModelSurface consists of a set of vertices, forming polygons using the same material/shader (since 1.5.0).

  • string getDefaultMaterial() Get the name of the default material for this surface, i.e. the name of the material without any skin applied.
  • string getActiveMaterial() Get the name of the currently mapped material (with skin applied). DEPRECATED, will be removed with DR 1.7.0
  • int getNumTriangles() Returns the number of tris of this surface.
  • int getNumVertices() Returns the number of vertices of this surface.
  • ArbitraryMeshVertex getVertex(int vertexIndex) Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.
  • ModelPolygon getPolygon(int polygonIndex) Returns a specific polygon from this model surface. Don't expect this to be fast as things are returned by value. This is merely to provide read access to the model polygons for scripts and plugins.
ArbitraryMeshVertex

An ArbitraryMeshVertex is a structure representing a model vertex. It holds the 3D coordinates, the texture coordinates, normal, tangent and bitangent vectors as well as the vertex colour (since 1.5.0).

  • Vector2 texcoord The 2D texture coordinates
  • Vector3 vertex The 3D coordinates
  • Vector3 normal The vertex normal
  • Vector3 tangent The tangent vector
  • Vector3 bitangent The bitangent vector
  • Vector3 colour The vertex colour
ModelPolygon

A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).

  • ArbitraryMeshVertex a The first vertex of this polygon
  • ArbitraryMeshVertex b The second vertex of this polygon
  • ArbitraryMeshVertex c The third vertex of this polygon

Entity Classes

GlobalEntityClassManager

The global entity class manager provides methods to retrieve existing entity classes. It also holds all the model definitions, which carry information about meshes and animations.

  • EntityClass findClass(string classname) Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.
  • forEachEntityClass(EntityClassVisitor visitor) Iterates over all existing entity classes using the given visitor object.
  • ModelDef findModel(string modelDefName) Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.
  • forEachModelDef(ModelDefVisitor visitor) Iterates over all existing model definitions using the given visitor object.

(Note: forEachEntityClass has been introduced in DarkRadiant 1.7.0, it was previously named forEach)

EntityClassVisitor

An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:

  • visit(EntityClass eclass) Is called for each known EntityClass.

This code example can be used as template when writing scripts for entityclasses; it shows how to print the "editor_usage" spawnarg of each entityDef:

# Test implementing a eclass visitor interface
class TestVisitor(EntityClassVisitor) :
	def visit(self, eclass):
		print eclass.getAttribute('editor_usage').getValue()

eclassVisitor = TestVisitor()
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)

ModelDefVisitor

A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:

  • visit(ModelDef modelDef) Is called for each known model declaration.

This code example can be used as template when writing scripts for model definitions; it shows how to print the "mesh" property of each modelDef:

# Test implementing a model def visitor interface
class TestModelDefVisitor(ModelDefVisitor) :
	def visit(self, modelDef):
		print(modelDef.mesh)

modelDefVisitor = TestModelDefVisitor()
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)

EntityClass

An EntityClass represents what modders know as entityDef. An entityDef represents a collection of spawnargs, pre-defining a certain entity type. Its interface is pretty simple:

  • isNull Returns true if this entityclass is a NULL object, i.e. is empty. This is usually the case if an nonexisting eclass was requested from the GlobalEntityClassManager.
  • bool isOfType(string className) Returns true if this eclass is of type or inherits from the given entity class name. className is treated case-sensitively. (new in 1.8.1)
  • EntityClassAttribute getAttribute(string key) Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.

EntityClassAttribute

An EntityClassAttribute represents a spawnarg on a given entityDef. It contains not only the key and the value, but also additional information about its type and (possibly) a description.

  • getName() Returns the name of this attribute (i.e. the key), for example: "spawnclass".
  • getValue() Returns the value of this attribute.
  • getType() Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.
  • getDescription() Returns the description, as provided by an "editor_*" spawnarg.
  • inherited Returns TRUE if this attribute has been inherited from a parent entityDef.

(Note: up to DarkRadiant 1.6.1 the accessors to the entityclass attribute values were named "name", "value", "type" and "description", this has been changed to member methods in 1.7.0+.)

ModelDef

A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.

  • name The name of this modelDef.
  • mesh The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.
  • skin The skin property. This is empty if no skin is used by this model.
  • parent The parent def this modelDef is inheriting from.
  • anims The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.
# Try to find the modeldef of the builder forger
modelDef = GlobalEntityClassManager.findModel('builderforger')
print('ModelDef mesh for builderforger = ' + modelDef.mesh)

# Iterate over all the animations for this modelDef
for anim in modelDef.anims:
	print(anim.key())
	print(' = ')
	print(anim.data())
	print()

GlobalEntityCreator

The entity creator can be used (as the name implies) to create entities in the scene.

It offers two flavours (so-called overloads) of the method "createEntity":

  • SceneNode createEntity(string entityClassName) Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"
  • SceneNode createEntity(EntityClass eclass) Create an entity of the given class, as acquired by the GlobalEntityClassManager

After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.

GlobalCommandSystem

The global command system can be used to execute DarkRadiant commands, as entered manually in the console.

  • execute(string command) Executes the given string command.
  • addStatement(string statementName, string str) Adds the given <str> as new statement with the given name.
  • removeCommand Removes the command with the given name from the command system.

Example:

# Test the commandsystem (this stretches the texture of the selection by 10%)
GlobalCommandSystem.execute('texscale "0 0.1"')

GlobalFileSystem

This global object allows the client to browse the so-called Virtual File System, which lists both the contents of the mod folders ("base", "darkmod", etc.) as well as the contents of the PK4 files in them.

  • forEachFile(string baseDir, string extension, FileVisitor visitor, int depth) Traverses the virtual filesystem, taking "baseDir" as starting point (e.g. "models/"), using "extension" to filter the visiited files and the given "visitor" to visit each file. The depth parameter can be used to restrict the traversal to a maximum folder depth.
  • string findFile(string relativeFilename) Returns the absolute filename for the given relative filename.
  • string findRoot(string absFilename) Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.
  • string readTextFile(string relativeFilename) Returns the full text contents of the given filename.
  • int getFileCount(string filename) Returns the number of files in the VFS matching the given filename.

FileVisitor

A FileVisitor is needed to traverse the GlobalFileSystem using its forEachFile() method. The visitor just needs to provide a single "visit" method, which is called for each matching file.

  • visit(string filename) Is called by forEachFile() for each matching filename.

GlobalGameManager

The GlobalGameManager object knows about all the available games. DarkRadiant supports a number of different "games", with each being defined in its own .game file in the install/ folder.

  • string getUserEnginePath() Returns the user's local engine path, on POSIX systems this might point to the folder in the home directory, e.g. ~/.doom3/ if it exists. If no engine directory is found in the home directory, the regular engine path is returned, e.g. /usr/local/doom3 or c:\games\doom3 (since 2.2.0)
  • string getModPath() Returns the current mod path, e.g. C:\Games\Doom3\darkmod, or ~/.doom3/darkmod. Returns the mod base path if the mod path itself is empty.
  • string getModBasePath() Returns the current mod base path, e.g. C:\Games\Doom3\gathers, or ~/.doom3/gathers. can be an empty string if fs_game_base is not set.
  • string getFSGame() Returns the value of the fs_game parameter in the preferences.
  • string getFSGameBase() Returns the value of the fs_game_base parameter in the preferences.
  • Game currentGame() Returns the active game object.
  • StringVector getVFSSearchPaths Returns a list of strings with the current search path, i.e. the search priorities. Topmost folder are searched first. The list can be iterated using Python's "for .. in .." construct.

Game

  • string getKeyValue(string key) Returns a key value as defined in the .game file for this game object. E.g. "basegame" will return "base" for the Doom 3 game.

GlobalRegistry

The registry allows storing persistent data for the application. Use this to save information for use in later script calls (e.g. to store the last filename). The DarkRadiant registry is XML-based, so the keys are actually XPaths. Be specific and use distinct xpath specifications, for instance user/scripts/aseExport/recentFilename

  • string get(path) Returns the string value for the given path. Returns empty if nothing found.
  • set(path, value) Set the string value for the given path, overwriting any existing value.

GlobalGrid

The GlobalGrid object can be used to set the grid size of the current viewports.

  • int getGridPower() Returns the currently active grid size in powers of two. The value is in the range [-3 .. 8], with -3 mapping to 0.125 and 8 mapping to 256.
  • setGridSize(int gridsize) Set the current grid size to the given power of two. The value must be in the range [-3 .. 8], with -3 referring to 0.125 and 8 referring to 256.
  • float getGridSize()Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)
  • gridDown() Decreases the grid size (stops at 0.125)
  • gridUp() Increases the grid size (stops at 256)

GlobalMap

The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:

  • SceneNode getWorldSpawn() Returns the worldspawn of the currently loaded map. This can be a NULL node if no map is active or no worldspawn has been created yet.
  • string getMapName() Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.

Math Objects

The most important math objects as used by the internal C++ code are exposed to scripting. This includes the most widely used three-component vector "Vector3" as well as the axis aligned bounding box object AABB, among others.

Vector2

A Vector2 is a two-component floating point vector.

  • x Returns a reference to the first component x of this vector.
  • y Returns a reference to the second component y of this vector.
  • float getLength() Returns the length of this vector.
  • float getLengthSquared() Returns the squared length (x^2 + y^2)
  • float dot(Vector2 other) Returns the result of the inner product of this Vector2 with a second Vector2.
  • Vector2 crossProduct(Vector2 other) Returns the resulting vector of the cross product of this Vector2 with one another.

Vector3

A Vector3 is a three-component floating point vector.

  • x Returns a reference to the first component x of this vector.
  • y Returns a reference to the second component y of this vector.
  • z Returns a reference to the third component z of this vector.
  • float getLength() Returns the length of this vector.
  • float getLengthSquared() Returns the squared length (x^2 + y^2 + z^2)
  • float dot(Vector3 other) Returns the result of the inner product of this Vector3 with a second Vector3.
  • Vector3 crossProduct(Vector3 other) Returns the resulting vector of the cross product of this Vector3 with one another.
  • Vector3 getNormalised() Returns a normalised copy of this vector, leaves this vector untouched.
  • normalise() Normalises this vector. After this call, this vector is a unit vector.
  • Vector3 getInversed() Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.
  • float angle(Vector3 other) Returns the angle between this vector and the "other" Vector3.
  • float max() Returns the maximum absolute value of all three components.
  • float min() Returns the minimum absolute value of all three components.
  • bool isParallel(Vector3 other) Returns true (1) if this vector is parallel to the "other" vector.

Vector4 / Quaternion

A Vector4 is a four-component floating-point Vector, also used to represent Quaternions. Both Quaternion and Vector4 are valid object types and implement the same interface.

  • x Returns a reference to the first component x of this vector.
  • y Returns a reference to the second component y of this vector.
  • z Returns a reference to the third component z of this vector.
  • w Returns a reference to the fourth component w of this vector.
  • float dot(Vector4 other) Returns the result of the inner product of this Vector4 with a second Vector4.
  • Vector3 getProjected() Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.

Vector Arithmetics

All Vector objects support the most important operators, each compatible with a Vector of the same type.

  • +
  • -
  • +=
  • -=
  • < (lesser than, only supported by Vector2 and Vector3)

AABB

AABB is an abbreviation of "Axis-Aligned Bounding Box". An AABB can be seen as rectangular box, providing an outer bound of the object it contains. Each two planes of an AABB are parallel to one of the orthogonal xy, yz and xz planes.

  • AABB() Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.
  • AABB(Vector3 origin, Vector3 extents) Constructs a valid bounding box, using the given origin and extents.
  • Vector3 origin This property can be used to access the center Vector3 of this bounding box.
  • extents This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)
  • bool isValid() Returns true (1) if this AABB is valid.
  • float getRadius() Returns the radius of this bounding box, i.e. the length of the "extents" vector.
  • includePoint(Vector3 other) Modifies this bounding box to include the given point, extending it when necessary.
  • includeAABB(AABB other) Modifies this bounding box to include the given AABB, extending it when necessary.

GlobalRadiant

The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.

  • EntityNode findEntityByClassname(string name) Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.

Example:

worldspawn = Radiant.findEntityByClassname("worldspawn")
worldspawn.setKeyValue('test', 'success')
print('Worldspawn edited')

GlobalSelectionSystem

The GlobalSelectionSystem object is the one managing the current selection. It provides methods to globally change selection states and to iterate over the existing selection.

  • SelectionInfo getSelectionInfo() Returns the reference to the internal counters of the selectionsystem, which can be used to check how many objects of which type are currently selected.
  • foreachSelected(SelectionVisitor visitor) Visits the current selection using the given Visitor object (not counting components).
  • foreachSelectedComponent(SelectionVisitor visitor) Visits the current component selection using the given Visitor object.
  • setSelectedAll(bool selected) Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).
  • setSelectedAllComponents(bool selected) Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).
  • SceneNode ultimateSelected() Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().
  • SceneNode penultimateSelected() Returns a reference to the penultimate selected object. Will throw an exception if called with less than two objects selected, so check first using getSelectionInfo().

SelectionInfo

This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.

  • int totalCount The total number of selected objects, including components.
  • int patchCount The number of selected patches.
  • int brushCount The number of selected brushes.
  • int entityCount The number of selected entities.
  • int componentCount The number of selected components (Faces, Edges, Vertices).

GlobalSelectionSetManager

The GlobalSelectionSetManager object is the one maintaining the selection sets in the scene. It provides methods to create/delete selection sets and to iterate over the existing set. (Since 1.4.0.)

  • foreachSelectionSet(SelectionSetVisitor visitor) Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.
  • SelectionSet createSelectionSet(string name) Creates a new selection set or overwrites the existing one with the given name.
  • deleteSelectionSet(string name) Deletes the named selection set.
  • deleteAllSelectionSets() Deletes ALL selection sets (irreversibly).
  • SelectionSet findSelectionSet(string name) Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.

SelectionSet

This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)

  • string getName() Returns the name of this selection set.
  • bool empty() Returns TRUE if this selection set is empty.
  • clear() Empties this selection set.
  • select() Selects all members/nodes of this selection set.
  • deselect() De-selects all members/nodes of this selection set.
  • assignFromCurrentScene() Clears this set and loads the currently selected nodes in the scene as new members into this set.

GlobalMaterialManager

This object holds all the shaders as parsed from the material (.mtr) files in the materials/ folders. Use this to retrieve a given material object and get information about them.

  • foreachShader(ShaderVisitor visitor) Visit each known shader with the given visitor object.
  • Shader getMaterialForName(string name) Returns the shader object for the given name. Returns a NULL object if nothing is found (isNull() will return true).

ShaderVisitor

A ShaderVisitor is needed for the GlobalMaterialManager.foreachShader() method to iterate over known materials.

  • visit(Shader s) Is invoked by the foreachShader() routine for each shader, passing the object along.

This example script will print all materials and the files they're defined in:

# This is the shader visitor object we will use to traverse the materials
class TestShaderVisitor(ShaderVisitor) :
	def visit(self, shader):
		if not shader.isNull():
			print('Found shader: ' + shader.getName() + ' defined in ' + shader.getShaderFileName())

shadervisitor = TestShaderVisitor()
GlobalMaterialManager.foreachShader(shadervisitor)

Shader

The shader object wraps around a known material, holding information about the shader stages and other things.

  • bool isNull() Returns true (1) if this a NULL material.
  • string getName() Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"
  • string getShaderFileName() Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")
  • string getDescription() Returns the description string as parsed from the material.
  • bool isVisible() Returns true if this shader is visible, i.e. not currently filtered.
  • bool isAmbientLight() Returns true (1) if this is an ambient light material.
  • bool isBlendLight() Returns true (1) if this is a blend light material.
  • bool isFogLight() Returns true (1) if this is a fog light material.

GlobalDialogManager

The dialog manager allows you to create popup messages and dialog windows and offers functions to customise them. The interface is like this, see the paragraphs below for some examples:

  • Dialog createDialog(string title) Creates and returns a new Dialog object with the given window title.
  • Dialog createMessageBox(string title, string text, MessageType type) Creates and returns a new popup message object (a popup message is just a specialised dialog, hence the same return type). The MessageType is an "enum" value (see below) and determines which buttons and which icon is displayed in the popup.

Dialog

Once you've created a new Dialog object, it offers the following functions:

  • setTitle(string title): Sets the window title of the dialog, if this hasn't been passed to the createDialog() method already. This way the title can be changed after creation.
  • Dialog.Result run() Displays the dialogs and waits until the user hits any button.
  • Handle addLabel(string labelText) Adds a label with the given text.
  • Handle addComboBox(string label, StringVector options) Adds a combo (dropdown) box with the given options (see below for an example about how to do that).
  • Handle addEntryBox(string label) Adds a text entry box.
  • Handle addPathEntry(string label, bool foldersOnly) Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.
  • Handle addSpinButton(string label, float min, float max, float step, int digits) Adds a spin button with the given limits [min..max] and the given step size. Floating point values are allowed. (Note: the "digits" parameter was added with DR 1.5.0+).
  • Handle addCheckbox(string label) Adds a simple checkbox (can be ticked on or off).
  • string getElementValue(Handle handle) Retrieves the current value of the element behind the given Handle. Returns an empty string if the Handle is invalid or not known to the dialog.
  • setElementValue(Handle handle, string value). Sets the value of the element specified by the given Handle. The given string is de-serialised into the dialog widgets (e.g. to set the value of a combo box in the dialog to a specific option, just pass the string value of that option). You can also set the "value" of labels in the dialog.

You'll notice that the add* methods return a Handle. This is an unsigned integer carrying the ID of the created element, so that it can be referenced later. Be sure to save that handle into a Python variable if you need to retrieve the value of the added element later down the road.

When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the add*() methods on the dialog objects to add some elements to it. The elements are inserted in the exact order of the calls, top to bottom, so if you call dialog.addLabel() followed by dialog.addEntryBox() the label will be added first and will be located above the entry box. See below for an example for each of the add*() methods listed above.

MessageType

  • Dialog.CONFIRM: The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.
  • Dialog.ASK: The message is decorated with a "question" image and offers the buttons YES and NO.
  • Dialog.WARNING: The message has a warning sign on it and has a simple OK button.
  • Dialog.ERROR: The message has an error image (a "stop" sign) on it and has a simple OK button.
  • Dialog.YESNOCANCEL: The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.

Result

When a dialog is finished running, the result is returned by the run() method. It can be one of several:

  • Dialog.CANCELLED: The dialog has been cancelled, either by a click on the "Cancel" button or by a click on the window's X element (usually in the upper right corner of the window).
  • Dialog.OK: The user clicked the OK button.
  • Dialog.NO: The user clicked the NO button.
  • Dialog.YES: The user clicked the YES button.

Examples

Popup messages are simple windows with just a string message. A popup message can be one of several types, like Questions, Confirmations, see below. It's best to learn from this example script:

dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm this", Dialog.CONFIRM)
dialog.run()

That's as simple as one can get: the code above just creates a new popup message of "CONFIRM" type with "Confirmation Box" as title and "Confirm this" as body text (yes, HTML-like markup is allowed). After creation, the dialog is displayed to the user by calling the run() method. (The result returned by run() is ignored here, as it's not of interest for a confirm popup.

Dialogs are more complex. When calling createDialog() you'll receive an empty dialog window first, only equipped with OK and CANCEL buttons. By calling the add*() methods on the dialog objects, it's possible to add some elements to it, in the given call order:

# Test creating a new dialog
dialog = GlobalDialogManager.createDialog("Test")

# Add a label
dialog.addLabel("Testlabel")

# Add an entry box and remember the handle
entryHandle = dialog.addEntryBox("Entry")

# Add a spin button
dialog.addSpinButton("Spinner", 0, 10, 0.5)

# Add a combo box, the options must be passed in the form of a StringVector
options = StringVector()
options.append("Test1")
options.append("Test2")
dialog.addComboBox("Test", options)

# Add a simple checkbox
dialog.addCheckbox("TestCheckbox")

if dialog.run() == Dialog.OK:
     print("User clicked OK.")

GlobalSoundManager

The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.

  • SoundShader getSoundShader(string shaderName) Looks up the sound shader by name.
  • bool playSound(string fileName) Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.
  • stopSound() Stops the currently played sound.

SoundShader

This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.

  • bool isNull() Whether this sound shader is the null object (i.e. if the getSoundShader() routine did not find the named shader, a null object will be returned)
  • string getName() The name of this sound shader
  • SoundRadii getRadii() The Radii object containing min/max values.
  • StringVector getSoundFileList() Returns the list of sound files used in this shader (by their VFS path).

SoundRadii

This is the object returned by SoundShader.getRadii().

  • float getMin(bool inMetres) Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.
  • setMin(float min, bool inMetres) Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.
  • float getMax(bool inMetres) Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.
  • setMax(float max, bool inMetres) Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.

Example Code

soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')

if not soundshader.isNull():
	print('Name of this sound shader: ' + soundshader.getName())

	radii = soundshader.getRadii()

	print('Minimum radius in meters: ' + str(radii.getMin(1)))
	print('Maximum radius in meters: ' + str(radii.getMax(1)))

	fileList = soundshader.getSoundFileList()
	for i in range(0, len(fileList)):
		print(' Sound file used by this shader: ' + fileList[i])

	if (len(fileList) > 0):
		GlobalSoundManager.playSound(fileList[0])