https://wiki.thedarkmod.com/api.php?action=feedcontributions&user=Greebo&feedformat=atomThe DarkMod Wiki - User contributions [en]2024-03-29T11:59:31ZUser contributionsMediaWiki 1.39.5https://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&diff=30956DarkRadiant - Compiling in Linux2024-01-13T09:50:22Z<p>Greebo: /* Obtain the source */</p>
<hr />
<div>== Install Required Packages ==<br />
<br />
=== Ubuntu 22.10 and later ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config libxml2-dev libsigc++-2.0-dev libftgl-dev libglew-dev libjpeg-dev<br />
sudo apt-get install libalut-dev libvorbis-dev libwxgtk3.2-dev libglib2.0-dev libeigen3-dev python3-dev libgtest-dev libgit2-dev<br />
<br />
=== Ubuntu 20.04 to 22.04 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config zlib1g-dev libjpeg-dev libxml2-dev libsigc++-2.0-dev libgtest-dev libeigen3-dev<br />
sudo apt-get install libwxgtk3.0-gtk3-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev libgit2-dev<br />
<br />
=== openSUSE Tumbleweed ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo zypper install git cmake gcc-c++ gettext-tools zlib-devel libjpeg62-devel libxml2-devel libsigc++2-devel gtest<br />
sudo zypper install wxWidgets-3_0-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python38-devel<br />
<br />
=== Mageia 8 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo urpmi git cmake make gcc-c++ libzlib-devel libjpeg-devel libwxgtku3.0-devel libsigc++2.0-devel <br />
sudo urpmi libftgl-devel libglew-devel libpython3-devel libopenal-devel libfreealut-devel libvorbis-devel lib64gtest-devel<br />
<br />
=== Debian 10 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git cmake pkg-config gettext zlib1g-dev libjpeg-dev libwxgtk3.0-dev libgtest-dev libeigen3-dev libgit2-dev<br />
sudo apt-get install libxml2-dev libsigc++-2.0-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== Fedora 26 / 25 ===<br />
Copy and paste the following into a terminal:<br />
<br />
sudo dnf install git automake libtool gcc-c++ zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel libsigc++20-devel <br />
sudo dnf install libpng12-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python-devel pybind11-devel<br />
<br />
Note that the wxGTK package does not yet support Wayland environments, which is the default since Fedora 25 (DarkRadiant will just segfault during startup). You'll need to [https://fedoraproject.org/wiki/Changes/WaylandByDefault deactivate it] for the moment being.<br />
<br />
=== Arch Linux ===<br />
The following packages are required after starting from an Anarchy installation using Gnome as Window Manager. <br />
<br />
sudo pacman -S cmake wxgtk3 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== Manjaro ===<br />
The following packages are required:<br />
sudo pacman -S cmake base-devel wxgtk3 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== CentOS 7 x64 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo yum -y install gcc gcc-c++ git automake libtool zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel <br />
sudo yum -y install libsigc++20-devel ftgl-devel glew-devel boost-devel openal-soft-devel freealut-devel libvorbis-devel python-devel<br />
<br />
CentOS 7 ships with an older compiler, so you'll need to install a more recent GCC first (following the directions on [https://stackoverflow.com/questions/36327805/how-to-install-gcc-5-3-with-yum-on-centos-7-2 stackoverflow]):<br />
<br />
sudo yum install centos-release-scl <br />
sudo yum install devtoolset-4-gcc*<br />
scl enable devtoolset-4 bash<br />
<br />
Note that the <tt>wxGTK3-devel</tt> package doesn't create a <tt>wx-config</tt> symlink in the <tt>/usr/bin</tt> directory, that's why you need to pass an additional <tt>--with-wx-config=/usr/bin/wx-config-3.0</tt> argument to the ./configure script below, like this:<br />
<br />
./configure --enable-darkmod-plugins --with-wx-config=/usr/bin/wx-config-3.0<br />
<br />
=== Slackware 14.2 ===<br />
<br />
Slackware doesn't provide precompiled packages on the one hand (unlike Debian or Arch), but already ships with a lot of libraries on the other. Stuff like git, automake, libtools and development libraries like zlib and boost are already present, but wxWidgets, openAL, ALut and FTGL need to be installed by means of a SlackBuild script. The following has been done in Slackware 14.2, so your mileage may vary.<br />
<br />
Download the Source tarballs and the SlackBuild packages from these URLs:<br />
<br />
* https://slackbuilds.org/repository/14.2/libraries/wxGTK3/<br />
* https://slackbuilds.org/repository/14.2/libraries/ftgl/<br />
* https://slackbuilds.org/repository/14.2/libraries/OpenAL/<br />
* https://slackbuilds.org/repository/14.2/libraries/freealut/<br />
<br />
Download and extract the SlackBuild <tt>.tar.gz</tt> files in your <tt>~/Downloads</tt> folder (or anywhere else where you want to have them). For instance, the wxGTK3 package can be untar'd like this:<br />
<br />
tar xzf wxGTK3.tar.gz<br />
cd wxGTK3<br />
chmod +x wxGTK3.SlackBuild<br />
<br />
Do this for all of the above libraries, that should give you the directories <tt>ftgl/</tt>, <tt>OpenAL/</tt>, <tt>wxGTK3/</tt> and <tt>freealut/</tt>. Next, download the Source Tarballs (the <tt>.tar.bz2</tt>) files from the links above and place them next to the corresponding SlackBuild script. Then run the scripts for each of them and install the build output in your system in a second step:<br />
<br />
./wxGTK3.SlackBuild<br />
<br />
This produced (on my end at least) the package <tt>/tmp/wxGTK3-3.0.2-i486-2_SBo.tgz</tt> which can be installed by the <tt>installpkg</tt> command:<br />
<br />
installpkg /tmp/wxGTK3-3.0.2-i486-2_SBo.tgz<br />
<br />
Do the same for the rest of the libraries (ftgl, OpenAL, freealut). Be aware that the freealut package depends on the OpenAL package, so you need to do the OpenAL one first. Once you have these installed, you can proceed to the build section (<tt>git clone</tt> and <tt>configure</tt> and <tt>make</tt>).<br />
<br />
=== Gentoo ===<br />
<br />
DarkRadiant can be built and installed from an unofficial ebuild repository (overlay). The easiest way to do this is with [https://packages.gentoo.org/packages/app-portage/layman app-portage/layman], which must be installed with the <tt>git</tt> use flag.<br />
<br />
In the 'overlays' section in <tt>/etc/layman/layman.cfg</tt>, add:<br />
<br />
https://raw.githubusercontent.com/varingst/varingst-overlay/master/overlay.xml<br />
<br />
Then fetch and add the overlay:<br />
<br />
# layman -f -a varingst<br />
<br />
Now that the overlay is added, you can build and install DarkRadiant with Portage:<br />
<br />
# emerge darkradiant<br />
<br />
To sync the overlay, either do it manually with layman:<br />
<br />
# layman -s varingst<br />
<br />
Or look into the [https://wiki.gentoo.org/wiki/Project:Portage/Sync various ways to hook into the portage sync system].<br />
<br />
=== Building with a non-default g++ Compiler ===<br />
DarkRadiant's codebase makes use of C++17 features, in particular std::filesystem. Not all distributions ship with a compatible g++ compiler by default, but it's possible to install a more recent compiler suite. Get the compiler package and ensure that the makefiles are called with the correct setup, e.g.<br />
CXX="g++-5.1" cmake . && make && make install<br />
<br />
=== Older Distributions / Compiling DarkRadiant 1.8 and older ===<br />
The instructions about how to compile DR 1.8 (based on GTK) in distributions published in 2012 and older have been removed. They should still be in the [http://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&oldid=18927 history] of this page, should they ever be needed.<br />
<br />
== Obtain the source ==<br />
<br />
Make sure you have the git client installed, this is covered in the package installation commands above. <br />
Next, change to the directory where you want the source code to be in and then clone the Git repository with:<br />
<br />
git clone https://github.com/codereader/DarkRadiant.git<br />
<br />
Once the initial clone is done, the source can be updated to the latest version from inside the working directory with:<br />
<br />
git pull<br />
<br />
== Configure and Compile ==<br />
DarkRadiant employs the CMake build system under Linux as used in many open-source projects. Make sure you have the CMake toolchain downloaded, this is covered in the package installation commands above.<br />
<br />
To build DarkRadiant, run the typical chain of CMake and make commands:<br />
<br />
cmake .<br />
make<br />
[sudo] make install<br />
<br />
By the above, a release build will be created; if a debug build is required pass the <tt>-DCMAKE_BUILD_TYPE=Debug</tt> option to the cmake command script.<br />
<br />
Other points to note about the configure process:<br />
<br />
* The DarkMod-specific plugins are built by default, the <tt>-DENABLE_DM_PLUGINS=OFF</tt> argument will disable them.<br />
* The CMake script autodetects required dependencies, and will conditionally enable optional components of DarkRadiant (such as the sound plugin) based on what it finds.<br />
* For quick testing of a DarkRadiant build, it is desirable to install it into a temporary location rather than the default of <tt>/usr/local</tt>; for this, simply pass a prefix option such as <tt>-DCMAKE_INSTALL_PREFIX=/tmp/dr</tt> to cmake, after which DarkRadiant will be installed in <tt>/tmp/dr/bin/darkradiant</tt>.<br />
<br />
=== Multiprocessor Systems ===<br />
<br />
You can pass the <tt>--jobs=N</tt> parameter to make:<br />
make --jobs=2<br />
to use more than one processor for the compilation. This will eat lots of RAM, so don't do this on machines with little available memory.<br />
<br />
=== Building a .deb package ===<br />
<br />
To build a Debian/Ubuntu package, simply run<br />
<br />
dpkg-buildpackage -rfakeroot<br />
<br />
in the main <tt>darkradiant</tt> directory. The .deb will be created in the parent directory.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=30464DarkRadiant Script Reference2023-01-02T06:12:22Z<p>Greebo: /* Material */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== MeshVertex =====<br />
A MeshVertex 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).<br />
(This type has been named ArbitraryMeshVertex until 2.14.)<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three MeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>MeshVertex a</tt> The first vertex of this polygon<br />
* <tt>MeshVertex b</tt> The second vertex of this polygon<br />
* <tt>MeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== GlobalDeclarationManager ===<br />
The declaration manager (available since 3.1.0) offers methods to interact with the declarations like Materials, Skins, ModelDefs defined throughout the mod. It can iterate through existing declarations, find them, manipulate them and even save them back to disk. See also the [https://github.com/codereader/DarkRadiant/blob/master/install/scripts/test.py Test Python Script] (scripts/test.py) in DarkRadiant's installation location.<br />
<br />
* <tt>Declaration findDeclaration(Declaration.Type type, string name)</tt> Finds a named declaration. If the declaration is not found, a NULL object is returned, see <tt>Declaration.isNull</tt>.<br />
* <tt>Declaration findOrCreateDeclaration(Declaration.Type type, string name)</tt> Finds an existing named declaration or creates an empty one if no declaration with that name exists yet. Will always return a non-null object.<br />
* <tt>Declaration foreachDeclaration(Declaration.Type type, DeclarationVisitor visitor)</tt> Calls the <tt>visit</tt> method of the given visitor class, see the example below.<br />
* <tt>bool renameDeclaration(Declaration.Type type, string oldName, string newName)</tt> Renames the declaration from oldName to newName. The new name must not be in use by any other declaration, and it must be different from oldName, otherwise renaming will fail. Returns true if the old declaration existed and could successfully be renamed, false on any failure.<br />
* <tt>removeDeclaration(Declaration.Type type, string name)</tt> Removes the given declaration from the internal dictionaries. This doesn't remove the declaration from the source files, so this operation will not survive a reloadDeclarations command. Used to remove temporary decls in edit scenarios.<br />
* <tt>reloadDeclarations()</tt> Reload all declarations. All declaration references your script may hold will stay intact, only their contents will be refreshed.<br />
* <tt>saveDeclaration(Declaration decl)</tt> Saves the given declaration to a physical declaration file. Depending on the original location of the declaration the outcome will be different (see notes below).<br />
<br />
'''Notes on saveDeclaration'''<br />
<br />
It is required for the declaration to have valid file information set on its syntax block, otherwise the declaration manager will not know where to save it to.<br />
* Case #1: Newly created declarations (created through findOrCreateDeclaration): The decl will be appended to the given file. The file will be created if required.<br />
* Case #2: Existing declarations (with their original file being a physical file): The decl in the file will be replaced with its new syntax block. All the content before and after the declaration will be left untouched.<br />
* Case #3: Existing declarations (with their original file being stored within a PK4): The decl file will be copied and saved to its corresponding physical location, effectively creating a file that will override the one in the PK4. The decl will be merged into the file just like in case #2<br />
<br />
==== Declaration.Type ====<br />
An enumeration of the available decl types supported by DarkRadiant:<br />
* Declaration.Type.'''Material'''<br />
* Declaration.Type.'''Table'''<br />
* Declaration.Type.'''EntityDef'''<br />
* Declaration.Type.'''SoundShader'''<br />
* Declaration.Type.'''ModelDef'''<br />
* Declaration.Type.'''Particle'''<br />
* Declaration.Type.'''Skin'''<br />
<br />
==== Declaration ====<br />
Represents a generic declaration as defined in the .mtr, .skin and .def files throughout the active mod or mission project.<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through DeclarationManager.findDeclaration<br />
* <tt>string getDeclName()</tt> Returns the name of this declaration, e.g. "textures/common/caulk"<br />
* <tt>Type getDeclType()</tt> Returns the declaration type, e.g. Declaration.Type.Skin<br />
* <tt>DeclarationBlockSyntax getBlockSyntax()</tt> Returns the syntax block containing the raw source text<br />
* <tt>setBlockSyntax(DeclarationBlockSyntax syntax)</tt> Assigns a new syntax block to this declaration<br />
* <tt>string getDeclFilePath()</tt> Returns the mod-relative path of the file this declaration has been defined in (e.g. "materials/test.mtr")<br />
* <tt>setDeclFilePath(string folder, string filename)</tt> Sets the mod-relative folder and filename of this declaration (useful right before saving a newly created declaration), Example: setDeclFilePath("materials/", "test.mtr")<br />
<br />
==== DeclarationBlockSyntax ====<br />
The syntax block contains the raw text contents as found in the file the declaration was defined in. The <tt>contents</tt> property holds the source text excluding the name and the outermost surrounding curly braces, so only the inner part is stored here. It can be modified and saved back into a declaration using <tt>setBlockSyntax</tt>.<br />
* <tt>typeName</tt> Returns typename as defined in the source file (can also be empty if none was specified)<br />
* <tt>name</tt> Returns the name of this block<br />
* <tt>contents</tt> Returns the raw contents of this block, excluding the name and the outermost surrounding curly braces<br />
* <tt>modName</tt> Returns the name of the mod/FM/project this block has been declared in.<br />
<br />
==== DeclarationVisitor ====<br />
A DeclarationVisitor can be used to iterate over all existing declarations of a given type. It just needs a single method definition named visit:<br />
* <tt>visit(Declaration decl)</tt> Is called for each known Declaration.<br />
<br />
This code example can be used as template when writing scripts for declarations; it shows how to print the name and filename of each skin declaration:<br />
import darkradiant as dr<br />
<br />
# Test implementing a DeclarationManager interface<br />
class TestDeclarationVisitor(dr.DeclarationVisitor) :<br />
def visit(self, decl):<br />
print(str(decl.getDeclType()) + ": " + decl.getDeclName() + " defined in " + decl.getDeclFilePath())<br />
<br />
visitor= TestDeclarationVisitor()<br />
GlobalDeclarationManager.foreachDeclaration(Declaration.Type.Skin, visitor)<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
* <tt>EntityNode findEntityName(string name)</tt> Returns the entity with the given name in the current scenegraph. Returns a NULL node if nothing is found (since 3.6.0).<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
Or:<br />
worldspawn = Radiant.findEntityByName("world")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
* <tt>Material.FrobStageType getFrobStageType()</tt> Returns the frob stage type used by this material. (since 3.8.0) - see [[#Material.FrobStageType|FrobStageType]]<br />
* <tt>setFrobStageType(Material.FrobStageType type)</tt> Sets the frob stage type used by this material. (since 3.8.0)<br />
* <tt>string getFrobStageMapExpressionString()</tt> Returns the frob stage map expression used for frob stage type TEXTURE. (since 3.8.0)<br />
* <tt>setFrobStageMapExpressionFromString(string expression)</tt> Sets the frob stage map expression used for frob stage type TEXTURE. (since 3.8.0)<br />
* <tt>Vector3 getFrobStageRgbParameter(int index)</tt> Returns one of the two frob stage RGB parameters (index can be 0 or 1), as used by this material. (since 3.8.0)<br />
* <tt>setFrobStageParameter(double value)</tt> Assigns the same value to all three RGB components of the frob stage parameter with the given index (which can be 0 or 1). (since 3.8.0)<br />
* <tt>setFrobStageRgbParameter(Vector3 rgb)</tt> Sets the RGB components of the frob stage parameter with the given index (which can be 0 or 1). (since 3.8.0)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
==== Material.FrobStageType ====<br />
Frob stage types supported by TDM 2.11+, see also the descriptive comments on the [https://bugs.thedarkmod.com/view.php?id=5427#c15337 corresponding tracker entry]<br />
* Material.FrobStageType.'''DEFAULT'''<br />
* Material.FrobStageType.'''DIFFUSE''' <br />
* Material.FrobStageType.'''TEXTURE''' <br />
* Material.FrobStageType.'''NONE'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
=== GlobalFxManager ===<br />
The FX manager (available since 3.3.0) exposes methods to interact with FX declarations.<br />
<br />
* <tt>FxDeclaration findFx(string name)</tt> Finds a named FX declaration. If the declaration is not found, a NULL object is returned, see <tt>FxDeclaration.isNull</tt>.<br />
<br />
Example code: <br />
fx = GlobalFxManager.findFx("fx/sparks")<br />
<br />
if not fx.isNull:<br />
print(fx.getDeclName())<br />
<br />
==== FxDeclaration ====<br />
Represents an FX declaration as defined in the .fx file. It inherits all methods from a generic '''Declaration''' object (see DeclarationManager interface).<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through GlobalFxManager.findFx<br />
* <tt>string getBindTo()</tt> Returns the name of this declaration, e.g. "fx/sparks"<br />
* <tt>int getNumActions()</tt> Returns the number of actions defined in this effect.<br />
* <tt>FxAction getAction(int index)</tt> Returns the i-th action (index is starting with 0)<br />
<br />
==== FxAction ====<br />
The FxAction object offers methods to check the various values set on a single action block.<br />
* <tt>FxAction.Type getActionType()</tt> Returns the type of this action, see '''FxAction.Type''' below.<br />
* <tt>string getName()</tt> Returns the name of this action (which might be an empty string)<br />
* <tt>float getDelayInSeconds()</tt> Returns the action delay in seconds<br />
* <tt>float getDurationInSeconds()</tt> Action duration in seconds, before it is killed or restarted<br />
* <tt>bool getIgnoreMaster()</tt> True: Don't shake the entity this effect is attached to<br />
* <tt>float getShakeTimeInSeconds()</tt> Shake parameter<br />
* <tt>float getShakeAmplitude()</tt> Shake parameter<br />
* <tt>float getShakeDistance()</tt> Shake parameter<br />
* <tt>bool getShakeFalloff()</tt> Shake parameter<br />
* <tt>float getShakeImpulse()</tt> Shake parameter<br />
* <tt>bool getNoShadows()</tt> if this is 1, the light in this effect doesn't cast shadows<br />
* <tt>string getFireSiblingAction()</tt> Causes the sibling action to happen when this action does<br />
* <tt>float getRandomDelay()</tt> Let the delay be random between min and max (in seconds). If both are 0.0 no random delay is active and the regular delay is used instead<br />
* <tt>float getRotate()</tt> According to the docs this is not used<br />
* <tt>bool getTrackOrigin()</tt> Move around with the entity (vs stationary after spawning)<br />
* <tt>bool getRestart()</tt> If this is 1, the action starts again after the 'duration' has run out<br />
* <tt>float getFadeInTimeInSeconds()</tt> Fade in the RGB of the light or model over <time> seconds<br />
* <tt>float getFadeOutTimeInSeconds()</tt> Fade out the light/model. Ignored if fadeIn is set, you can use 2 separate actions (tied together with uselight) if you want a light to fade in and out.<br />
* <tt>float getDecalSize()</tt> Size of the decal (corresponds to "size" keyword)<br />
* <tt>Vector3 getOffset()</tt> Offset from the origin of the entity (or bind point) this action is located at<br />
* <tt>Vector3 getAxis()</tt> Axis of the model, mutually exclusive with angle<br />
* <tt>Vector3 getAngle()</tt> Alternate way of setting the axis of the model<br />
* <tt>string getUseLight()</tt> Returns the name of the action containing the light which should be used<br />
* <tt>string getUseModel()</tt> Modify the model in a named sibling action. Can be used to fade out a particle in a sibling.<br />
* <tt>string getAttachLight()</tt> Attach to external light (a light not defined in the effect) for fading.<br />
* <tt>string getAttachEntity()</tt> Attach to an external entity<br />
* <tt>string getLaunchProjectileDef()</tt> Launches a projectile of the given entityDef<br />
* <tt>string getLightMaterialName()</tt> If not empty, this action spawns a light with this material<br />
* <tt>Vector3 getLightRgbColour()</tt> For FxAction.Type.Light actions, this defines the RGB colour components<br />
* <tt>float getLightRadius()</tt> For FxAction.Type.Light actions, this defines the radius of the spawned light<br />
* <tt>string getModelName()</tt> Return the name of the model or particle<br />
* <tt>string getDecalMaterialName()</tt> For FxAction.Type.Decal actions, this defines the decal material name<br />
* <tt>bool getParticleTrackVelocity()</tt> Unused according to docs<br />
* <tt>string getSoundShaderName()</tt> For FxAction.Type.:Sound actions: start a sound (on any channel)<br />
* <tt>string getShockwaveDefName()</tt> For FxAction.Type.Shockwave actions: the name of the shockwave entityDef<br />
<br />
==== FxAction.Type ====<br />
An enumeration of the available FX action types known to DarkRadiant:<br />
* FxAction.Type.'''Undefined'''<br />
* FxAction.Type.'''Light'''<br />
* FxAction.Type.'''Particle'''<br />
* FxAction.Type.'''Decal'''<br />
* FxAction.Type.'''Model'''<br />
* FxAction.Type.'''Sound'''<br />
* FxAction.Type.'''Shake'''<br />
* FxAction.Type.'''AttachLight'''<br />
* FxAction.Type.'''AttachEntity'''<br />
* FxAction.Type.'''Launch'''<br />
* FxAction.Type.'''Shockwave'''<br />
<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=30463DarkRadiant Script Reference2023-01-02T06:11:03Z<p>Greebo: /* Material */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== MeshVertex =====<br />
A MeshVertex 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).<br />
(This type has been named ArbitraryMeshVertex until 2.14.)<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three MeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>MeshVertex a</tt> The first vertex of this polygon<br />
* <tt>MeshVertex b</tt> The second vertex of this polygon<br />
* <tt>MeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== GlobalDeclarationManager ===<br />
The declaration manager (available since 3.1.0) offers methods to interact with the declarations like Materials, Skins, ModelDefs defined throughout the mod. It can iterate through existing declarations, find them, manipulate them and even save them back to disk. See also the [https://github.com/codereader/DarkRadiant/blob/master/install/scripts/test.py Test Python Script] (scripts/test.py) in DarkRadiant's installation location.<br />
<br />
* <tt>Declaration findDeclaration(Declaration.Type type, string name)</tt> Finds a named declaration. If the declaration is not found, a NULL object is returned, see <tt>Declaration.isNull</tt>.<br />
* <tt>Declaration findOrCreateDeclaration(Declaration.Type type, string name)</tt> Finds an existing named declaration or creates an empty one if no declaration with that name exists yet. Will always return a non-null object.<br />
* <tt>Declaration foreachDeclaration(Declaration.Type type, DeclarationVisitor visitor)</tt> Calls the <tt>visit</tt> method of the given visitor class, see the example below.<br />
* <tt>bool renameDeclaration(Declaration.Type type, string oldName, string newName)</tt> Renames the declaration from oldName to newName. The new name must not be in use by any other declaration, and it must be different from oldName, otherwise renaming will fail. Returns true if the old declaration existed and could successfully be renamed, false on any failure.<br />
* <tt>removeDeclaration(Declaration.Type type, string name)</tt> Removes the given declaration from the internal dictionaries. This doesn't remove the declaration from the source files, so this operation will not survive a reloadDeclarations command. Used to remove temporary decls in edit scenarios.<br />
* <tt>reloadDeclarations()</tt> Reload all declarations. All declaration references your script may hold will stay intact, only their contents will be refreshed.<br />
* <tt>saveDeclaration(Declaration decl)</tt> Saves the given declaration to a physical declaration file. Depending on the original location of the declaration the outcome will be different (see notes below).<br />
<br />
'''Notes on saveDeclaration'''<br />
<br />
It is required for the declaration to have valid file information set on its syntax block, otherwise the declaration manager will not know where to save it to.<br />
* Case #1: Newly created declarations (created through findOrCreateDeclaration): The decl will be appended to the given file. The file will be created if required.<br />
* Case #2: Existing declarations (with their original file being a physical file): The decl in the file will be replaced with its new syntax block. All the content before and after the declaration will be left untouched.<br />
* Case #3: Existing declarations (with their original file being stored within a PK4): The decl file will be copied and saved to its corresponding physical location, effectively creating a file that will override the one in the PK4. The decl will be merged into the file just like in case #2<br />
<br />
==== Declaration.Type ====<br />
An enumeration of the available decl types supported by DarkRadiant:<br />
* Declaration.Type.'''Material'''<br />
* Declaration.Type.'''Table'''<br />
* Declaration.Type.'''EntityDef'''<br />
* Declaration.Type.'''SoundShader'''<br />
* Declaration.Type.'''ModelDef'''<br />
* Declaration.Type.'''Particle'''<br />
* Declaration.Type.'''Skin'''<br />
<br />
==== Declaration ====<br />
Represents a generic declaration as defined in the .mtr, .skin and .def files throughout the active mod or mission project.<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through DeclarationManager.findDeclaration<br />
* <tt>string getDeclName()</tt> Returns the name of this declaration, e.g. "textures/common/caulk"<br />
* <tt>Type getDeclType()</tt> Returns the declaration type, e.g. Declaration.Type.Skin<br />
* <tt>DeclarationBlockSyntax getBlockSyntax()</tt> Returns the syntax block containing the raw source text<br />
* <tt>setBlockSyntax(DeclarationBlockSyntax syntax)</tt> Assigns a new syntax block to this declaration<br />
* <tt>string getDeclFilePath()</tt> Returns the mod-relative path of the file this declaration has been defined in (e.g. "materials/test.mtr")<br />
* <tt>setDeclFilePath(string folder, string filename)</tt> Sets the mod-relative folder and filename of this declaration (useful right before saving a newly created declaration), Example: setDeclFilePath("materials/", "test.mtr")<br />
<br />
==== DeclarationBlockSyntax ====<br />
The syntax block contains the raw text contents as found in the file the declaration was defined in. The <tt>contents</tt> property holds the source text excluding the name and the outermost surrounding curly braces, so only the inner part is stored here. It can be modified and saved back into a declaration using <tt>setBlockSyntax</tt>.<br />
* <tt>typeName</tt> Returns typename as defined in the source file (can also be empty if none was specified)<br />
* <tt>name</tt> Returns the name of this block<br />
* <tt>contents</tt> Returns the raw contents of this block, excluding the name and the outermost surrounding curly braces<br />
* <tt>modName</tt> Returns the name of the mod/FM/project this block has been declared in.<br />
<br />
==== DeclarationVisitor ====<br />
A DeclarationVisitor can be used to iterate over all existing declarations of a given type. It just needs a single method definition named visit:<br />
* <tt>visit(Declaration decl)</tt> Is called for each known Declaration.<br />
<br />
This code example can be used as template when writing scripts for declarations; it shows how to print the name and filename of each skin declaration:<br />
import darkradiant as dr<br />
<br />
# Test implementing a DeclarationManager interface<br />
class TestDeclarationVisitor(dr.DeclarationVisitor) :<br />
def visit(self, decl):<br />
print(str(decl.getDeclType()) + ": " + decl.getDeclName() + " defined in " + decl.getDeclFilePath())<br />
<br />
visitor= TestDeclarationVisitor()<br />
GlobalDeclarationManager.foreachDeclaration(Declaration.Type.Skin, visitor)<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
* <tt>EntityNode findEntityName(string name)</tt> Returns the entity with the given name in the current scenegraph. Returns a NULL node if nothing is found (since 3.6.0).<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
Or:<br />
worldspawn = Radiant.findEntityByName("world")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
* <tt>Material.FrobStageType getFrobStageType()</tt> Returns the frob stage type used by this material. (since 3.8.0)<br />
* <tt>setFrobStageType(Material.FrobStageType type)</tt> Sets the frob stage type used by this material. (since 3.8.0)<br />
* <tt>string getFrobStageMapExpressionString()</tt> Returns the frob stage map expression used for frob stage type TEXTURE. (since 3.8.0)<br />
* <tt>setFrobStageMapExpressionFromString(string expression)</tt> Sets the frob stage map expression used for frob stage type TEXTURE. (since 3.8.0)<br />
* <tt>Vector3 getFrobStageRgbParameter(int index)</tt> Returns one of the two frob stage RGB parameters (index can be 0 or 1), as used by this material. (since 3.8.0)<br />
* <tt>setFrobStageParameter(double value)</tt> Assigns the same value to all three RGB components of the frob stage parameter with the given index (which can be 0 or 1). (since 3.8.0)<br />
* <tt>setFrobStageRgbParameter(Vector3 rgb)</tt> Sets the RGB components of the frob stage parameter with the given index (which can be 0 or 1). (since 3.8.0)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
==== Material.FrobStageType ====<br />
Frob stage types supported by TDM 2.11+, see also the descriptive comments on the [https://bugs.thedarkmod.com/view.php?id=5427#c15337 corresponding tracker entry]<br />
* Material.FrobStageType.'''DEFAULT'''<br />
* Material.FrobStageType.'''DIFFUSE''' <br />
* Material.FrobStageType.'''TEXTURE''' <br />
* Material.FrobStageType.'''NONE'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
=== GlobalFxManager ===<br />
The FX manager (available since 3.3.0) exposes methods to interact with FX declarations.<br />
<br />
* <tt>FxDeclaration findFx(string name)</tt> Finds a named FX declaration. If the declaration is not found, a NULL object is returned, see <tt>FxDeclaration.isNull</tt>.<br />
<br />
Example code: <br />
fx = GlobalFxManager.findFx("fx/sparks")<br />
<br />
if not fx.isNull:<br />
print(fx.getDeclName())<br />
<br />
==== FxDeclaration ====<br />
Represents an FX declaration as defined in the .fx file. It inherits all methods from a generic '''Declaration''' object (see DeclarationManager interface).<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through GlobalFxManager.findFx<br />
* <tt>string getBindTo()</tt> Returns the name of this declaration, e.g. "fx/sparks"<br />
* <tt>int getNumActions()</tt> Returns the number of actions defined in this effect.<br />
* <tt>FxAction getAction(int index)</tt> Returns the i-th action (index is starting with 0)<br />
<br />
==== FxAction ====<br />
The FxAction object offers methods to check the various values set on a single action block.<br />
* <tt>FxAction.Type getActionType()</tt> Returns the type of this action, see '''FxAction.Type''' below.<br />
* <tt>string getName()</tt> Returns the name of this action (which might be an empty string)<br />
* <tt>float getDelayInSeconds()</tt> Returns the action delay in seconds<br />
* <tt>float getDurationInSeconds()</tt> Action duration in seconds, before it is killed or restarted<br />
* <tt>bool getIgnoreMaster()</tt> True: Don't shake the entity this effect is attached to<br />
* <tt>float getShakeTimeInSeconds()</tt> Shake parameter<br />
* <tt>float getShakeAmplitude()</tt> Shake parameter<br />
* <tt>float getShakeDistance()</tt> Shake parameter<br />
* <tt>bool getShakeFalloff()</tt> Shake parameter<br />
* <tt>float getShakeImpulse()</tt> Shake parameter<br />
* <tt>bool getNoShadows()</tt> if this is 1, the light in this effect doesn't cast shadows<br />
* <tt>string getFireSiblingAction()</tt> Causes the sibling action to happen when this action does<br />
* <tt>float getRandomDelay()</tt> Let the delay be random between min and max (in seconds). If both are 0.0 no random delay is active and the regular delay is used instead<br />
* <tt>float getRotate()</tt> According to the docs this is not used<br />
* <tt>bool getTrackOrigin()</tt> Move around with the entity (vs stationary after spawning)<br />
* <tt>bool getRestart()</tt> If this is 1, the action starts again after the 'duration' has run out<br />
* <tt>float getFadeInTimeInSeconds()</tt> Fade in the RGB of the light or model over <time> seconds<br />
* <tt>float getFadeOutTimeInSeconds()</tt> Fade out the light/model. Ignored if fadeIn is set, you can use 2 separate actions (tied together with uselight) if you want a light to fade in and out.<br />
* <tt>float getDecalSize()</tt> Size of the decal (corresponds to "size" keyword)<br />
* <tt>Vector3 getOffset()</tt> Offset from the origin of the entity (or bind point) this action is located at<br />
* <tt>Vector3 getAxis()</tt> Axis of the model, mutually exclusive with angle<br />
* <tt>Vector3 getAngle()</tt> Alternate way of setting the axis of the model<br />
* <tt>string getUseLight()</tt> Returns the name of the action containing the light which should be used<br />
* <tt>string getUseModel()</tt> Modify the model in a named sibling action. Can be used to fade out a particle in a sibling.<br />
* <tt>string getAttachLight()</tt> Attach to external light (a light not defined in the effect) for fading.<br />
* <tt>string getAttachEntity()</tt> Attach to an external entity<br />
* <tt>string getLaunchProjectileDef()</tt> Launches a projectile of the given entityDef<br />
* <tt>string getLightMaterialName()</tt> If not empty, this action spawns a light with this material<br />
* <tt>Vector3 getLightRgbColour()</tt> For FxAction.Type.Light actions, this defines the RGB colour components<br />
* <tt>float getLightRadius()</tt> For FxAction.Type.Light actions, this defines the radius of the spawned light<br />
* <tt>string getModelName()</tt> Return the name of the model or particle<br />
* <tt>string getDecalMaterialName()</tt> For FxAction.Type.Decal actions, this defines the decal material name<br />
* <tt>bool getParticleTrackVelocity()</tt> Unused according to docs<br />
* <tt>string getSoundShaderName()</tt> For FxAction.Type.:Sound actions: start a sound (on any channel)<br />
* <tt>string getShockwaveDefName()</tt> For FxAction.Type.Shockwave actions: the name of the shockwave entityDef<br />
<br />
==== FxAction.Type ====<br />
An enumeration of the available FX action types known to DarkRadiant:<br />
* FxAction.Type.'''Undefined'''<br />
* FxAction.Type.'''Light'''<br />
* FxAction.Type.'''Particle'''<br />
* FxAction.Type.'''Decal'''<br />
* FxAction.Type.'''Model'''<br />
* FxAction.Type.'''Sound'''<br />
* FxAction.Type.'''Shake'''<br />
* FxAction.Type.'''AttachLight'''<br />
* FxAction.Type.'''AttachEntity'''<br />
* FxAction.Type.'''Launch'''<br />
* FxAction.Type.'''Shockwave'''<br />
<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=30462DarkRadiant Script Reference2023-01-02T06:05:51Z<p>Greebo: /* Material.FrobStageType */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== MeshVertex =====<br />
A MeshVertex 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).<br />
(This type has been named ArbitraryMeshVertex until 2.14.)<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three MeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>MeshVertex a</tt> The first vertex of this polygon<br />
* <tt>MeshVertex b</tt> The second vertex of this polygon<br />
* <tt>MeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== GlobalDeclarationManager ===<br />
The declaration manager (available since 3.1.0) offers methods to interact with the declarations like Materials, Skins, ModelDefs defined throughout the mod. It can iterate through existing declarations, find them, manipulate them and even save them back to disk. See also the [https://github.com/codereader/DarkRadiant/blob/master/install/scripts/test.py Test Python Script] (scripts/test.py) in DarkRadiant's installation location.<br />
<br />
* <tt>Declaration findDeclaration(Declaration.Type type, string name)</tt> Finds a named declaration. If the declaration is not found, a NULL object is returned, see <tt>Declaration.isNull</tt>.<br />
* <tt>Declaration findOrCreateDeclaration(Declaration.Type type, string name)</tt> Finds an existing named declaration or creates an empty one if no declaration with that name exists yet. Will always return a non-null object.<br />
* <tt>Declaration foreachDeclaration(Declaration.Type type, DeclarationVisitor visitor)</tt> Calls the <tt>visit</tt> method of the given visitor class, see the example below.<br />
* <tt>bool renameDeclaration(Declaration.Type type, string oldName, string newName)</tt> Renames the declaration from oldName to newName. The new name must not be in use by any other declaration, and it must be different from oldName, otherwise renaming will fail. Returns true if the old declaration existed and could successfully be renamed, false on any failure.<br />
* <tt>removeDeclaration(Declaration.Type type, string name)</tt> Removes the given declaration from the internal dictionaries. This doesn't remove the declaration from the source files, so this operation will not survive a reloadDeclarations command. Used to remove temporary decls in edit scenarios.<br />
* <tt>reloadDeclarations()</tt> Reload all declarations. All declaration references your script may hold will stay intact, only their contents will be refreshed.<br />
* <tt>saveDeclaration(Declaration decl)</tt> Saves the given declaration to a physical declaration file. Depending on the original location of the declaration the outcome will be different (see notes below).<br />
<br />
'''Notes on saveDeclaration'''<br />
<br />
It is required for the declaration to have valid file information set on its syntax block, otherwise the declaration manager will not know where to save it to.<br />
* Case #1: Newly created declarations (created through findOrCreateDeclaration): The decl will be appended to the given file. The file will be created if required.<br />
* Case #2: Existing declarations (with their original file being a physical file): The decl in the file will be replaced with its new syntax block. All the content before and after the declaration will be left untouched.<br />
* Case #3: Existing declarations (with their original file being stored within a PK4): The decl file will be copied and saved to its corresponding physical location, effectively creating a file that will override the one in the PK4. The decl will be merged into the file just like in case #2<br />
<br />
==== Declaration.Type ====<br />
An enumeration of the available decl types supported by DarkRadiant:<br />
* Declaration.Type.'''Material'''<br />
* Declaration.Type.'''Table'''<br />
* Declaration.Type.'''EntityDef'''<br />
* Declaration.Type.'''SoundShader'''<br />
* Declaration.Type.'''ModelDef'''<br />
* Declaration.Type.'''Particle'''<br />
* Declaration.Type.'''Skin'''<br />
<br />
==== Declaration ====<br />
Represents a generic declaration as defined in the .mtr, .skin and .def files throughout the active mod or mission project.<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through DeclarationManager.findDeclaration<br />
* <tt>string getDeclName()</tt> Returns the name of this declaration, e.g. "textures/common/caulk"<br />
* <tt>Type getDeclType()</tt> Returns the declaration type, e.g. Declaration.Type.Skin<br />
* <tt>DeclarationBlockSyntax getBlockSyntax()</tt> Returns the syntax block containing the raw source text<br />
* <tt>setBlockSyntax(DeclarationBlockSyntax syntax)</tt> Assigns a new syntax block to this declaration<br />
* <tt>string getDeclFilePath()</tt> Returns the mod-relative path of the file this declaration has been defined in (e.g. "materials/test.mtr")<br />
* <tt>setDeclFilePath(string folder, string filename)</tt> Sets the mod-relative folder and filename of this declaration (useful right before saving a newly created declaration), Example: setDeclFilePath("materials/", "test.mtr")<br />
<br />
==== DeclarationBlockSyntax ====<br />
The syntax block contains the raw text contents as found in the file the declaration was defined in. The <tt>contents</tt> property holds the source text excluding the name and the outermost surrounding curly braces, so only the inner part is stored here. It can be modified and saved back into a declaration using <tt>setBlockSyntax</tt>.<br />
* <tt>typeName</tt> Returns typename as defined in the source file (can also be empty if none was specified)<br />
* <tt>name</tt> Returns the name of this block<br />
* <tt>contents</tt> Returns the raw contents of this block, excluding the name and the outermost surrounding curly braces<br />
* <tt>modName</tt> Returns the name of the mod/FM/project this block has been declared in.<br />
<br />
==== DeclarationVisitor ====<br />
A DeclarationVisitor can be used to iterate over all existing declarations of a given type. It just needs a single method definition named visit:<br />
* <tt>visit(Declaration decl)</tt> Is called for each known Declaration.<br />
<br />
This code example can be used as template when writing scripts for declarations; it shows how to print the name and filename of each skin declaration:<br />
import darkradiant as dr<br />
<br />
# Test implementing a DeclarationManager interface<br />
class TestDeclarationVisitor(dr.DeclarationVisitor) :<br />
def visit(self, decl):<br />
print(str(decl.getDeclType()) + ": " + decl.getDeclName() + " defined in " + decl.getDeclFilePath())<br />
<br />
visitor= TestDeclarationVisitor()<br />
GlobalDeclarationManager.foreachDeclaration(Declaration.Type.Skin, visitor)<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
* <tt>EntityNode findEntityName(string name)</tt> Returns the entity with the given name in the current scenegraph. Returns a NULL node if nothing is found (since 3.6.0).<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
Or:<br />
worldspawn = Radiant.findEntityByName("world")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
==== Material.FrobStageType ====<br />
Frob stage types supported by TDM 2.11+, see also the descriptive comments on the [https://bugs.thedarkmod.com/view.php?id=5427#c15337 corresponding tracker entry]<br />
* Material.FrobStageType.'''DEFAULT'''<br />
* Material.FrobStageType.'''DIFFUSE''' <br />
* Material.FrobStageType.'''TEXTURE''' <br />
* Material.FrobStageType.'''NONE'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
=== GlobalFxManager ===<br />
The FX manager (available since 3.3.0) exposes methods to interact with FX declarations.<br />
<br />
* <tt>FxDeclaration findFx(string name)</tt> Finds a named FX declaration. If the declaration is not found, a NULL object is returned, see <tt>FxDeclaration.isNull</tt>.<br />
<br />
Example code: <br />
fx = GlobalFxManager.findFx("fx/sparks")<br />
<br />
if not fx.isNull:<br />
print(fx.getDeclName())<br />
<br />
==== FxDeclaration ====<br />
Represents an FX declaration as defined in the .fx file. It inherits all methods from a generic '''Declaration''' object (see DeclarationManager interface).<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through GlobalFxManager.findFx<br />
* <tt>string getBindTo()</tt> Returns the name of this declaration, e.g. "fx/sparks"<br />
* <tt>int getNumActions()</tt> Returns the number of actions defined in this effect.<br />
* <tt>FxAction getAction(int index)</tt> Returns the i-th action (index is starting with 0)<br />
<br />
==== FxAction ====<br />
The FxAction object offers methods to check the various values set on a single action block.<br />
* <tt>FxAction.Type getActionType()</tt> Returns the type of this action, see '''FxAction.Type''' below.<br />
* <tt>string getName()</tt> Returns the name of this action (which might be an empty string)<br />
* <tt>float getDelayInSeconds()</tt> Returns the action delay in seconds<br />
* <tt>float getDurationInSeconds()</tt> Action duration in seconds, before it is killed or restarted<br />
* <tt>bool getIgnoreMaster()</tt> True: Don't shake the entity this effect is attached to<br />
* <tt>float getShakeTimeInSeconds()</tt> Shake parameter<br />
* <tt>float getShakeAmplitude()</tt> Shake parameter<br />
* <tt>float getShakeDistance()</tt> Shake parameter<br />
* <tt>bool getShakeFalloff()</tt> Shake parameter<br />
* <tt>float getShakeImpulse()</tt> Shake parameter<br />
* <tt>bool getNoShadows()</tt> if this is 1, the light in this effect doesn't cast shadows<br />
* <tt>string getFireSiblingAction()</tt> Causes the sibling action to happen when this action does<br />
* <tt>float getRandomDelay()</tt> Let the delay be random between min and max (in seconds). If both are 0.0 no random delay is active and the regular delay is used instead<br />
* <tt>float getRotate()</tt> According to the docs this is not used<br />
* <tt>bool getTrackOrigin()</tt> Move around with the entity (vs stationary after spawning)<br />
* <tt>bool getRestart()</tt> If this is 1, the action starts again after the 'duration' has run out<br />
* <tt>float getFadeInTimeInSeconds()</tt> Fade in the RGB of the light or model over <time> seconds<br />
* <tt>float getFadeOutTimeInSeconds()</tt> Fade out the light/model. Ignored if fadeIn is set, you can use 2 separate actions (tied together with uselight) if you want a light to fade in and out.<br />
* <tt>float getDecalSize()</tt> Size of the decal (corresponds to "size" keyword)<br />
* <tt>Vector3 getOffset()</tt> Offset from the origin of the entity (or bind point) this action is located at<br />
* <tt>Vector3 getAxis()</tt> Axis of the model, mutually exclusive with angle<br />
* <tt>Vector3 getAngle()</tt> Alternate way of setting the axis of the model<br />
* <tt>string getUseLight()</tt> Returns the name of the action containing the light which should be used<br />
* <tt>string getUseModel()</tt> Modify the model in a named sibling action. Can be used to fade out a particle in a sibling.<br />
* <tt>string getAttachLight()</tt> Attach to external light (a light not defined in the effect) for fading.<br />
* <tt>string getAttachEntity()</tt> Attach to an external entity<br />
* <tt>string getLaunchProjectileDef()</tt> Launches a projectile of the given entityDef<br />
* <tt>string getLightMaterialName()</tt> If not empty, this action spawns a light with this material<br />
* <tt>Vector3 getLightRgbColour()</tt> For FxAction.Type.Light actions, this defines the RGB colour components<br />
* <tt>float getLightRadius()</tt> For FxAction.Type.Light actions, this defines the radius of the spawned light<br />
* <tt>string getModelName()</tt> Return the name of the model or particle<br />
* <tt>string getDecalMaterialName()</tt> For FxAction.Type.Decal actions, this defines the decal material name<br />
* <tt>bool getParticleTrackVelocity()</tt> Unused according to docs<br />
* <tt>string getSoundShaderName()</tt> For FxAction.Type.:Sound actions: start a sound (on any channel)<br />
* <tt>string getShockwaveDefName()</tt> For FxAction.Type.Shockwave actions: the name of the shockwave entityDef<br />
<br />
==== FxAction.Type ====<br />
An enumeration of the available FX action types known to DarkRadiant:<br />
* FxAction.Type.'''Undefined'''<br />
* FxAction.Type.'''Light'''<br />
* FxAction.Type.'''Particle'''<br />
* FxAction.Type.'''Decal'''<br />
* FxAction.Type.'''Model'''<br />
* FxAction.Type.'''Sound'''<br />
* FxAction.Type.'''Shake'''<br />
* FxAction.Type.'''AttachLight'''<br />
* FxAction.Type.'''AttachEntity'''<br />
* FxAction.Type.'''Launch'''<br />
* FxAction.Type.'''Shockwave'''<br />
<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=30243DarkRadiant Script Reference2022-11-12T09:19:37Z<p>Greebo: /* GlobalRadiant */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== MeshVertex =====<br />
A MeshVertex 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).<br />
(This type has been named ArbitraryMeshVertex until 2.14.)<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three MeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>MeshVertex a</tt> The first vertex of this polygon<br />
* <tt>MeshVertex b</tt> The second vertex of this polygon<br />
* <tt>MeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== GlobalDeclarationManager ===<br />
The declaration manager (available since 3.1.0) offers methods to interact with the declarations like Materials, Skins, ModelDefs defined throughout the mod. It can iterate through existing declarations, find them, manipulate them and even save them back to disk. See also the [https://github.com/codereader/DarkRadiant/blob/master/install/scripts/test.py Test Python Script] (scripts/test.py) in DarkRadiant's installation location.<br />
<br />
* <tt>Declaration findDeclaration(Declaration.Type type, string name)</tt> Finds a named declaration. If the declaration is not found, a NULL object is returned, see <tt>Declaration.isNull</tt>.<br />
* <tt>Declaration findOrCreateDeclaration(Declaration.Type type, string name)</tt> Finds an existing named declaration or creates an empty one if no declaration with that name exists yet. Will always return a non-null object.<br />
* <tt>Declaration foreachDeclaration(Declaration.Type type, DeclarationVisitor visitor)</tt> Calls the <tt>visit</tt> method of the given visitor class, see the example below.<br />
* <tt>bool renameDeclaration(Declaration.Type type, string oldName, string newName)</tt> Renames the declaration from oldName to newName. The new name must not be in use by any other declaration, and it must be different from oldName, otherwise renaming will fail. Returns true if the old declaration existed and could successfully be renamed, false on any failure.<br />
* <tt>removeDeclaration(Declaration.Type type, string name)</tt> Removes the given declaration from the internal dictionaries. This doesn't remove the declaration from the source files, so this operation will not survive a reloadDeclarations command. Used to remove temporary decls in edit scenarios.<br />
* <tt>reloadDeclarations()</tt> Reload all declarations. All declaration references your script may hold will stay intact, only their contents will be refreshed.<br />
* <tt>saveDeclaration(Declaration decl)</tt> Saves the given declaration to a physical declaration file. Depending on the original location of the declaration the outcome will be different (see notes below).<br />
<br />
'''Notes on saveDeclaration'''<br />
<br />
It is required for the declaration to have valid file information set on its syntax block, otherwise the declaration manager will not know where to save it to.<br />
* Case #1: Newly created declarations (created through findOrCreateDeclaration): The decl will be appended to the given file. The file will be created if required.<br />
* Case #2: Existing declarations (with their original file being a physical file): The decl in the file will be replaced with its new syntax block. All the content before and after the declaration will be left untouched.<br />
* Case #3: Existing declarations (with their original file being stored within a PK4): The decl file will be copied and saved to its corresponding physical location, effectively creating a file that will override the one in the PK4. The decl will be merged into the file just like in case #2<br />
<br />
==== Declaration.Type ====<br />
An enumeration of the available decl types supported by DarkRadiant:<br />
* Declaration.Type.'''Material'''<br />
* Declaration.Type.'''Table'''<br />
* Declaration.Type.'''EntityDef'''<br />
* Declaration.Type.'''SoundShader'''<br />
* Declaration.Type.'''ModelDef'''<br />
* Declaration.Type.'''Particle'''<br />
* Declaration.Type.'''Skin'''<br />
<br />
==== Declaration ====<br />
Represents a generic declaration as defined in the .mtr, .skin and .def files throughout the active mod or mission project.<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through DeclarationManager.findDeclaration<br />
* <tt>string getDeclName()</tt> Returns the name of this declaration, e.g. "textures/common/caulk"<br />
* <tt>Type getDeclType()</tt> Returns the declaration type, e.g. Declaration.Type.Skin<br />
* <tt>DeclarationBlockSyntax getBlockSyntax()</tt> Returns the syntax block containing the raw source text<br />
* <tt>setBlockSyntax(DeclarationBlockSyntax syntax)</tt> Assigns a new syntax block to this declaration<br />
* <tt>string getDeclFilePath()</tt> Returns the mod-relative path of the file this declaration has been defined in (e.g. "materials/test.mtr")<br />
* <tt>setDeclFilePath(string folder, string filename)</tt> Sets the mod-relative folder and filename of this declaration (useful right before saving a newly created declaration), Example: setDeclFilePath("materials/", "test.mtr")<br />
<br />
==== DeclarationBlockSyntax ====<br />
The syntax block contains the raw text contents as found in the file the declaration was defined in. The <tt>contents</tt> property holds the source text excluding the name and the outermost surrounding curly braces, so only the inner part is stored here. It can be modified and saved back into a declaration using <tt>setBlockSyntax</tt>.<br />
* <tt>typeName</tt> Returns typename as defined in the source file (can also be empty if none was specified)<br />
* <tt>name</tt> Returns the name of this block<br />
* <tt>contents</tt> Returns the raw contents of this block, excluding the name and the outermost surrounding curly braces<br />
* <tt>modName</tt> Returns the name of the mod/FM/project this block has been declared in.<br />
<br />
==== DeclarationVisitor ====<br />
A DeclarationVisitor can be used to iterate over all existing declarations of a given type. It just needs a single method definition named visit:<br />
* <tt>visit(Declaration decl)</tt> Is called for each known Declaration.<br />
<br />
This code example can be used as template when writing scripts for declarations; it shows how to print the name and filename of each skin declaration:<br />
import darkradiant as dr<br />
<br />
# Test implementing a DeclarationManager interface<br />
class TestDeclarationVisitor(dr.DeclarationVisitor) :<br />
def visit(self, decl):<br />
print(str(decl.getDeclType()) + ": " + decl.getDeclName() + " defined in " + decl.getDeclFilePath())<br />
<br />
visitor= TestDeclarationVisitor()<br />
GlobalDeclarationManager.foreachDeclaration(Declaration.Type.Skin, visitor)<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
* <tt>EntityNode findEntityName(string name)</tt> Returns the entity with the given name in the current scenegraph. Returns a NULL node if nothing is found (since 3.6.0).<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
Or:<br />
worldspawn = Radiant.findEntityByName("world")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
=== GlobalFxManager ===<br />
The FX manager (available since 3.3.0) exposes methods to interact with FX declarations.<br />
<br />
* <tt>FxDeclaration findFx(string name)</tt> Finds a named FX declaration. If the declaration is not found, a NULL object is returned, see <tt>FxDeclaration.isNull</tt>.<br />
<br />
Example code: <br />
fx = GlobalFxManager.findFx("fx/sparks")<br />
<br />
if not fx.isNull:<br />
print(fx.getDeclName())<br />
<br />
==== FxDeclaration ====<br />
Represents an FX declaration as defined in the .fx file. It inherits all methods from a generic '''Declaration''' object (see DeclarationManager interface).<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through GlobalFxManager.findFx<br />
* <tt>string getBindTo()</tt> Returns the name of this declaration, e.g. "fx/sparks"<br />
* <tt>int getNumActions()</tt> Returns the number of actions defined in this effect.<br />
* <tt>FxAction getAction(int index)</tt> Returns the i-th action (index is starting with 0)<br />
<br />
==== FxAction ====<br />
The FxAction object offers methods to check the various values set on a single action block.<br />
* <tt>FxAction.Type getActionType()</tt> Returns the type of this action, see '''FxAction.Type''' below.<br />
* <tt>string getName()</tt> Returns the name of this action (which might be an empty string)<br />
* <tt>float getDelayInSeconds()</tt> Returns the action delay in seconds<br />
* <tt>float getDurationInSeconds()</tt> Action duration in seconds, before it is killed or restarted<br />
* <tt>bool getIgnoreMaster()</tt> True: Don't shake the entity this effect is attached to<br />
* <tt>float getShakeTimeInSeconds()</tt> Shake parameter<br />
* <tt>float getShakeAmplitude()</tt> Shake parameter<br />
* <tt>float getShakeDistance()</tt> Shake parameter<br />
* <tt>bool getShakeFalloff()</tt> Shake parameter<br />
* <tt>float getShakeImpulse()</tt> Shake parameter<br />
* <tt>bool getNoShadows()</tt> if this is 1, the light in this effect doesn't cast shadows<br />
* <tt>string getFireSiblingAction()</tt> Causes the sibling action to happen when this action does<br />
* <tt>float getRandomDelay()</tt> Let the delay be random between min and max (in seconds). If both are 0.0 no random delay is active and the regular delay is used instead<br />
* <tt>float getRotate()</tt> According to the docs this is not used<br />
* <tt>bool getTrackOrigin()</tt> Move around with the entity (vs stationary after spawning)<br />
* <tt>bool getRestart()</tt> If this is 1, the action starts again after the 'duration' has run out<br />
* <tt>float getFadeInTimeInSeconds()</tt> Fade in the RGB of the light or model over <time> seconds<br />
* <tt>float getFadeOutTimeInSeconds()</tt> Fade out the light/model. Ignored if fadeIn is set, you can use 2 separate actions (tied together with uselight) if you want a light to fade in and out.<br />
* <tt>float getDecalSize()</tt> Size of the decal (corresponds to "size" keyword)<br />
* <tt>Vector3 getOffset()</tt> Offset from the origin of the entity (or bind point) this action is located at<br />
* <tt>Vector3 getAxis()</tt> Axis of the model, mutually exclusive with angle<br />
* <tt>Vector3 getAngle()</tt> Alternate way of setting the axis of the model<br />
* <tt>string getUseLight()</tt> Returns the name of the action containing the light which should be used<br />
* <tt>string getUseModel()</tt> Modify the model in a named sibling action. Can be used to fade out a particle in a sibling.<br />
* <tt>string getAttachLight()</tt> Attach to external light (a light not defined in the effect) for fading.<br />
* <tt>string getAttachEntity()</tt> Attach to an external entity<br />
* <tt>string getLaunchProjectileDef()</tt> Launches a projectile of the given entityDef<br />
* <tt>string getLightMaterialName()</tt> If not empty, this action spawns a light with this material<br />
* <tt>Vector3 getLightRgbColour()</tt> For FxAction.Type.Light actions, this defines the RGB colour components<br />
* <tt>float getLightRadius()</tt> For FxAction.Type.Light actions, this defines the radius of the spawned light<br />
* <tt>string getModelName()</tt> Return the name of the model or particle<br />
* <tt>string getDecalMaterialName()</tt> For FxAction.Type.Decal actions, this defines the decal material name<br />
* <tt>bool getParticleTrackVelocity()</tt> Unused according to docs<br />
* <tt>string getSoundShaderName()</tt> For FxAction.Type.:Sound actions: start a sound (on any channel)<br />
* <tt>string getShockwaveDefName()</tt> For FxAction.Type.Shockwave actions: the name of the shockwave entityDef<br />
<br />
==== FxAction.Type ====<br />
An enumeration of the available FX action types known to DarkRadiant:<br />
* FxAction.Type.'''Undefined'''<br />
* FxAction.Type.'''Light'''<br />
* FxAction.Type.'''Particle'''<br />
* FxAction.Type.'''Decal'''<br />
* FxAction.Type.'''Model'''<br />
* FxAction.Type.'''Sound'''<br />
* FxAction.Type.'''Shake'''<br />
* FxAction.Type.'''AttachLight'''<br />
* FxAction.Type.'''AttachEntity'''<br />
* FxAction.Type.'''Launch'''<br />
* FxAction.Type.'''Shockwave'''<br />
<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=30242DarkRadiant Script Reference2022-11-12T09:19:26Z<p>Greebo: /* GlobalRadiant */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== MeshVertex =====<br />
A MeshVertex 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).<br />
(This type has been named ArbitraryMeshVertex until 2.14.)<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three MeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>MeshVertex a</tt> The first vertex of this polygon<br />
* <tt>MeshVertex b</tt> The second vertex of this polygon<br />
* <tt>MeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== GlobalDeclarationManager ===<br />
The declaration manager (available since 3.1.0) offers methods to interact with the declarations like Materials, Skins, ModelDefs defined throughout the mod. It can iterate through existing declarations, find them, manipulate them and even save them back to disk. See also the [https://github.com/codereader/DarkRadiant/blob/master/install/scripts/test.py Test Python Script] (scripts/test.py) in DarkRadiant's installation location.<br />
<br />
* <tt>Declaration findDeclaration(Declaration.Type type, string name)</tt> Finds a named declaration. If the declaration is not found, a NULL object is returned, see <tt>Declaration.isNull</tt>.<br />
* <tt>Declaration findOrCreateDeclaration(Declaration.Type type, string name)</tt> Finds an existing named declaration or creates an empty one if no declaration with that name exists yet. Will always return a non-null object.<br />
* <tt>Declaration foreachDeclaration(Declaration.Type type, DeclarationVisitor visitor)</tt> Calls the <tt>visit</tt> method of the given visitor class, see the example below.<br />
* <tt>bool renameDeclaration(Declaration.Type type, string oldName, string newName)</tt> Renames the declaration from oldName to newName. The new name must not be in use by any other declaration, and it must be different from oldName, otherwise renaming will fail. Returns true if the old declaration existed and could successfully be renamed, false on any failure.<br />
* <tt>removeDeclaration(Declaration.Type type, string name)</tt> Removes the given declaration from the internal dictionaries. This doesn't remove the declaration from the source files, so this operation will not survive a reloadDeclarations command. Used to remove temporary decls in edit scenarios.<br />
* <tt>reloadDeclarations()</tt> Reload all declarations. All declaration references your script may hold will stay intact, only their contents will be refreshed.<br />
* <tt>saveDeclaration(Declaration decl)</tt> Saves the given declaration to a physical declaration file. Depending on the original location of the declaration the outcome will be different (see notes below).<br />
<br />
'''Notes on saveDeclaration'''<br />
<br />
It is required for the declaration to have valid file information set on its syntax block, otherwise the declaration manager will not know where to save it to.<br />
* Case #1: Newly created declarations (created through findOrCreateDeclaration): The decl will be appended to the given file. The file will be created if required.<br />
* Case #2: Existing declarations (with their original file being a physical file): The decl in the file will be replaced with its new syntax block. All the content before and after the declaration will be left untouched.<br />
* Case #3: Existing declarations (with their original file being stored within a PK4): The decl file will be copied and saved to its corresponding physical location, effectively creating a file that will override the one in the PK4. The decl will be merged into the file just like in case #2<br />
<br />
==== Declaration.Type ====<br />
An enumeration of the available decl types supported by DarkRadiant:<br />
* Declaration.Type.'''Material'''<br />
* Declaration.Type.'''Table'''<br />
* Declaration.Type.'''EntityDef'''<br />
* Declaration.Type.'''SoundShader'''<br />
* Declaration.Type.'''ModelDef'''<br />
* Declaration.Type.'''Particle'''<br />
* Declaration.Type.'''Skin'''<br />
<br />
==== Declaration ====<br />
Represents a generic declaration as defined in the .mtr, .skin and .def files throughout the active mod or mission project.<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through DeclarationManager.findDeclaration<br />
* <tt>string getDeclName()</tt> Returns the name of this declaration, e.g. "textures/common/caulk"<br />
* <tt>Type getDeclType()</tt> Returns the declaration type, e.g. Declaration.Type.Skin<br />
* <tt>DeclarationBlockSyntax getBlockSyntax()</tt> Returns the syntax block containing the raw source text<br />
* <tt>setBlockSyntax(DeclarationBlockSyntax syntax)</tt> Assigns a new syntax block to this declaration<br />
* <tt>string getDeclFilePath()</tt> Returns the mod-relative path of the file this declaration has been defined in (e.g. "materials/test.mtr")<br />
* <tt>setDeclFilePath(string folder, string filename)</tt> Sets the mod-relative folder and filename of this declaration (useful right before saving a newly created declaration), Example: setDeclFilePath("materials/", "test.mtr")<br />
<br />
==== DeclarationBlockSyntax ====<br />
The syntax block contains the raw text contents as found in the file the declaration was defined in. The <tt>contents</tt> property holds the source text excluding the name and the outermost surrounding curly braces, so only the inner part is stored here. It can be modified and saved back into a declaration using <tt>setBlockSyntax</tt>.<br />
* <tt>typeName</tt> Returns typename as defined in the source file (can also be empty if none was specified)<br />
* <tt>name</tt> Returns the name of this block<br />
* <tt>contents</tt> Returns the raw contents of this block, excluding the name and the outermost surrounding curly braces<br />
* <tt>modName</tt> Returns the name of the mod/FM/project this block has been declared in.<br />
<br />
==== DeclarationVisitor ====<br />
A DeclarationVisitor can be used to iterate over all existing declarations of a given type. It just needs a single method definition named visit:<br />
* <tt>visit(Declaration decl)</tt> Is called for each known Declaration.<br />
<br />
This code example can be used as template when writing scripts for declarations; it shows how to print the name and filename of each skin declaration:<br />
import darkradiant as dr<br />
<br />
# Test implementing a DeclarationManager interface<br />
class TestDeclarationVisitor(dr.DeclarationVisitor) :<br />
def visit(self, decl):<br />
print(str(decl.getDeclType()) + ": " + decl.getDeclName() + " defined in " + decl.getDeclFilePath())<br />
<br />
visitor= TestDeclarationVisitor()<br />
GlobalDeclarationManager.foreachDeclaration(Declaration.Type.Skin, visitor)<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
* <tt>EntityNode findEntityName(string name)</tt> Returns the entity with the given name in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
Or:<br />
worldspawn = Radiant.findEntityByName("world")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
=== GlobalFxManager ===<br />
The FX manager (available since 3.3.0) exposes methods to interact with FX declarations.<br />
<br />
* <tt>FxDeclaration findFx(string name)</tt> Finds a named FX declaration. If the declaration is not found, a NULL object is returned, see <tt>FxDeclaration.isNull</tt>.<br />
<br />
Example code: <br />
fx = GlobalFxManager.findFx("fx/sparks")<br />
<br />
if not fx.isNull:<br />
print(fx.getDeclName())<br />
<br />
==== FxDeclaration ====<br />
Represents an FX declaration as defined in the .fx file. It inherits all methods from a generic '''Declaration''' object (see DeclarationManager interface).<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through GlobalFxManager.findFx<br />
* <tt>string getBindTo()</tt> Returns the name of this declaration, e.g. "fx/sparks"<br />
* <tt>int getNumActions()</tt> Returns the number of actions defined in this effect.<br />
* <tt>FxAction getAction(int index)</tt> Returns the i-th action (index is starting with 0)<br />
<br />
==== FxAction ====<br />
The FxAction object offers methods to check the various values set on a single action block.<br />
* <tt>FxAction.Type getActionType()</tt> Returns the type of this action, see '''FxAction.Type''' below.<br />
* <tt>string getName()</tt> Returns the name of this action (which might be an empty string)<br />
* <tt>float getDelayInSeconds()</tt> Returns the action delay in seconds<br />
* <tt>float getDurationInSeconds()</tt> Action duration in seconds, before it is killed or restarted<br />
* <tt>bool getIgnoreMaster()</tt> True: Don't shake the entity this effect is attached to<br />
* <tt>float getShakeTimeInSeconds()</tt> Shake parameter<br />
* <tt>float getShakeAmplitude()</tt> Shake parameter<br />
* <tt>float getShakeDistance()</tt> Shake parameter<br />
* <tt>bool getShakeFalloff()</tt> Shake parameter<br />
* <tt>float getShakeImpulse()</tt> Shake parameter<br />
* <tt>bool getNoShadows()</tt> if this is 1, the light in this effect doesn't cast shadows<br />
* <tt>string getFireSiblingAction()</tt> Causes the sibling action to happen when this action does<br />
* <tt>float getRandomDelay()</tt> Let the delay be random between min and max (in seconds). If both are 0.0 no random delay is active and the regular delay is used instead<br />
* <tt>float getRotate()</tt> According to the docs this is not used<br />
* <tt>bool getTrackOrigin()</tt> Move around with the entity (vs stationary after spawning)<br />
* <tt>bool getRestart()</tt> If this is 1, the action starts again after the 'duration' has run out<br />
* <tt>float getFadeInTimeInSeconds()</tt> Fade in the RGB of the light or model over <time> seconds<br />
* <tt>float getFadeOutTimeInSeconds()</tt> Fade out the light/model. Ignored if fadeIn is set, you can use 2 separate actions (tied together with uselight) if you want a light to fade in and out.<br />
* <tt>float getDecalSize()</tt> Size of the decal (corresponds to "size" keyword)<br />
* <tt>Vector3 getOffset()</tt> Offset from the origin of the entity (or bind point) this action is located at<br />
* <tt>Vector3 getAxis()</tt> Axis of the model, mutually exclusive with angle<br />
* <tt>Vector3 getAngle()</tt> Alternate way of setting the axis of the model<br />
* <tt>string getUseLight()</tt> Returns the name of the action containing the light which should be used<br />
* <tt>string getUseModel()</tt> Modify the model in a named sibling action. Can be used to fade out a particle in a sibling.<br />
* <tt>string getAttachLight()</tt> Attach to external light (a light not defined in the effect) for fading.<br />
* <tt>string getAttachEntity()</tt> Attach to an external entity<br />
* <tt>string getLaunchProjectileDef()</tt> Launches a projectile of the given entityDef<br />
* <tt>string getLightMaterialName()</tt> If not empty, this action spawns a light with this material<br />
* <tt>Vector3 getLightRgbColour()</tt> For FxAction.Type.Light actions, this defines the RGB colour components<br />
* <tt>float getLightRadius()</tt> For FxAction.Type.Light actions, this defines the radius of the spawned light<br />
* <tt>string getModelName()</tt> Return the name of the model or particle<br />
* <tt>string getDecalMaterialName()</tt> For FxAction.Type.Decal actions, this defines the decal material name<br />
* <tt>bool getParticleTrackVelocity()</tt> Unused according to docs<br />
* <tt>string getSoundShaderName()</tt> For FxAction.Type.:Sound actions: start a sound (on any channel)<br />
* <tt>string getShockwaveDefName()</tt> For FxAction.Type.Shockwave actions: the name of the shockwave entityDef<br />
<br />
==== FxAction.Type ====<br />
An enumeration of the available FX action types known to DarkRadiant:<br />
* FxAction.Type.'''Undefined'''<br />
* FxAction.Type.'''Light'''<br />
* FxAction.Type.'''Particle'''<br />
* FxAction.Type.'''Decal'''<br />
* FxAction.Type.'''Model'''<br />
* FxAction.Type.'''Sound'''<br />
* FxAction.Type.'''Shake'''<br />
* FxAction.Type.'''AttachLight'''<br />
* FxAction.Type.'''AttachEntity'''<br />
* FxAction.Type.'''Launch'''<br />
* FxAction.Type.'''Shockwave'''<br />
<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&diff=30039DarkRadiant - Compiling in Linux2022-10-31T18:34:16Z<p>Greebo: Ubuntu 22.10</p>
<hr />
<div>== Install Required Packages ==<br />
<br />
=== Ubuntu 22.10 and later ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config libxml2-dev libsigc++-2.0-dev libftgl-dev libglew-dev libjpeg-dev<br />
sudo apt-get install libalut-dev libvorbis-dev libwxgtk3.2-dev libglib2.0-dev libeigen3-dev python3-dev libgtest-dev libgit2-dev<br />
<br />
=== Ubuntu 20.04 to 22.04 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config zlib1g-dev libjpeg-dev libxml2-dev libsigc++-2.0-dev libgtest-dev libeigen3-dev<br />
sudo apt-get install libwxgtk3.0-gtk3-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev libgit2-dev<br />
<br />
=== openSUSE Tumbleweed ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo zypper install git cmake gcc-c++ gettext-tools zlib-devel libjpeg62-devel libxml2-devel libsigc++2-devel gtest<br />
sudo zypper install wxWidgets-3_0-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python38-devel<br />
<br />
=== Mageia 8 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo urpmi git cmake make gcc-c++ libzlib-devel libjpeg-devel libwxgtku3.0-devel libsigc++2.0-devel <br />
sudo urpmi libftgl-devel libglew-devel libpython3-devel libopenal-devel libfreealut-devel libvorbis-devel lib64gtest-devel<br />
<br />
=== Debian 10 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git cmake pkg-config gettext zlib1g-dev libjpeg-dev libwxgtk3.0-dev libgtest-dev libeigen3-dev libgit2-dev<br />
sudo apt-get install libxml2-dev libsigc++-2.0-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== Fedora 26 / 25 ===<br />
Copy and paste the following into a terminal:<br />
<br />
sudo dnf install git automake libtool gcc-c++ zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel libsigc++20-devel <br />
sudo dnf install libpng12-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python-devel pybind11-devel<br />
<br />
Note that the wxGTK package does not yet support Wayland environments, which is the default since Fedora 25 (DarkRadiant will just segfault during startup). You'll need to [https://fedoraproject.org/wiki/Changes/WaylandByDefault deactivate it] for the moment being.<br />
<br />
=== Arch Linux ===<br />
The following packages are required after starting from an Anarchy installation using Gnome as Window Manager. <br />
<br />
sudo pacman -S cmake wxgtk3 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== Manjaro ===<br />
The following packages are required:<br />
sudo pacman -S cmake base-devel wxgtk3 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== CentOS 7 x64 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo yum -y install gcc gcc-c++ git automake libtool zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel <br />
sudo yum -y install libsigc++20-devel ftgl-devel glew-devel boost-devel openal-soft-devel freealut-devel libvorbis-devel python-devel<br />
<br />
CentOS 7 ships with an older compiler, so you'll need to install a more recent GCC first (following the directions on [https://stackoverflow.com/questions/36327805/how-to-install-gcc-5-3-with-yum-on-centos-7-2 stackoverflow]):<br />
<br />
sudo yum install centos-release-scl <br />
sudo yum install devtoolset-4-gcc*<br />
scl enable devtoolset-4 bash<br />
<br />
Note that the <tt>wxGTK3-devel</tt> package doesn't create a <tt>wx-config</tt> symlink in the <tt>/usr/bin</tt> directory, that's why you need to pass an additional <tt>--with-wx-config=/usr/bin/wx-config-3.0</tt> argument to the ./configure script below, like this:<br />
<br />
./configure --enable-darkmod-plugins --with-wx-config=/usr/bin/wx-config-3.0<br />
<br />
=== Slackware 14.2 ===<br />
<br />
Slackware doesn't provide precompiled packages on the one hand (unlike Debian or Arch), but already ships with a lot of libraries on the other. Stuff like git, automake, libtools and development libraries like zlib and boost are already present, but wxWidgets, openAL, ALut and FTGL need to be installed by means of a SlackBuild script. The following has been done in Slackware 14.2, so your mileage may vary.<br />
<br />
Download the Source tarballs and the SlackBuild packages from these URLs:<br />
<br />
* https://slackbuilds.org/repository/14.2/libraries/wxGTK3/<br />
* https://slackbuilds.org/repository/14.2/libraries/ftgl/<br />
* https://slackbuilds.org/repository/14.2/libraries/OpenAL/<br />
* https://slackbuilds.org/repository/14.2/libraries/freealut/<br />
<br />
Download and extract the SlackBuild <tt>.tar.gz</tt> files in your <tt>~/Downloads</tt> folder (or anywhere else where you want to have them). For instance, the wxGTK3 package can be untar'd like this:<br />
<br />
tar xzf wxGTK3.tar.gz<br />
cd wxGTK3<br />
chmod +x wxGTK3.SlackBuild<br />
<br />
Do this for all of the above libraries, that should give you the directories <tt>ftgl/</tt>, <tt>OpenAL/</tt>, <tt>wxGTK3/</tt> and <tt>freealut/</tt>. Next, download the Source Tarballs (the <tt>.tar.bz2</tt>) files from the links above and place them next to the corresponding SlackBuild script. Then run the scripts for each of them and install the build output in your system in a second step:<br />
<br />
./wxGTK3.SlackBuild<br />
<br />
This produced (on my end at least) the package <tt>/tmp/wxGTK3-3.0.2-i486-2_SBo.tgz</tt> which can be installed by the <tt>installpkg</tt> command:<br />
<br />
installpkg /tmp/wxGTK3-3.0.2-i486-2_SBo.tgz<br />
<br />
Do the same for the rest of the libraries (ftgl, OpenAL, freealut). Be aware that the freealut package depends on the OpenAL package, so you need to do the OpenAL one first. Once you have these installed, you can proceed to the build section (<tt>git clone</tt> and <tt>configure</tt> and <tt>make</tt>).<br />
<br />
=== Gentoo ===<br />
<br />
DarkRadiant can be built and installed from an unofficial ebuild repository (overlay). The easiest way to do this is with [https://packages.gentoo.org/packages/app-portage/layman app-portage/layman], which must be installed with the <tt>git</tt> use flag.<br />
<br />
In the 'overlays' section in <tt>/etc/layman/layman.cfg</tt>, add:<br />
<br />
https://raw.githubusercontent.com/varingst/varingst-overlay/master/overlay.xml<br />
<br />
Then fetch and add the overlay:<br />
<br />
# layman -f -a varingst<br />
<br />
Now that the overlay is added, you can build and install DarkRadiant with Portage:<br />
<br />
# emerge darkradiant<br />
<br />
To sync the overlay, either do it manually with layman:<br />
<br />
# layman -s varingst<br />
<br />
Or look into the [https://wiki.gentoo.org/wiki/Project:Portage/Sync various ways to hook into the portage sync system].<br />
<br />
=== Building with a non-default g++ Compiler ===<br />
DarkRadiant's codebase makes use of C++17 features, in particular std::filesystem. Not all distributions ship with a compatible g++ compiler by default, but it's possible to install a more recent compiler suite. Get the compiler package and ensure that the makefiles are called with the correct setup, e.g.<br />
CXX="g++-5.1" cmake . && make && make install<br />
<br />
=== Older Distributions / Compiling DarkRadiant 1.8 and older ===<br />
The instructions about how to compile DR 1.8 (based on GTK) in distributions published in 2012 and older have been removed. They should still be in the [http://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&oldid=18927 history] of this page, should they ever be needed.<br />
<br />
== Obtain the source ==<br />
<br />
Make sure you have the git client installed, this is covered in the package installation commands above. <br />
Next, change to the directory where you want the source code to be in and then clone the Git repository with:<br />
<br />
git clone git://github.com/codereader/DarkRadiant.git --recurse-submodules<br />
<br />
Once the initial clone is done, the source can be updated to the latest version from inside the working directory with:<br />
<br />
git pull<br />
<br />
== Configure and Compile ==<br />
DarkRadiant employs the CMake build system under Linux as used in many open-source projects. Make sure you have the CMake toolchain downloaded, this is covered in the package installation commands above.<br />
<br />
To build DarkRadiant, run the typical chain of CMake and make commands:<br />
<br />
cmake .<br />
make<br />
[sudo] make install<br />
<br />
By the above, a release build will be created; if a debug build is required pass the <tt>-DCMAKE_BUILD_TYPE=Debug</tt> option to the cmake command script.<br />
<br />
Other points to note about the configure process:<br />
<br />
* The DarkMod-specific plugins are built by default, the <tt>-DENABLE_DM_PLUGINS=OFF</tt> argument will disable them.<br />
* The CMake script autodetects required dependencies, and will conditionally enable optional components of DarkRadiant (such as the sound plugin) based on what it finds.<br />
* For quick testing of a DarkRadiant build, it is desirable to install it into a temporary location rather than the default of <tt>/usr/local</tt>; for this, simply pass a prefix option such as <tt>-DCMAKE_INSTALL_PREFIX=/tmp/dr</tt> to cmake, after which DarkRadiant will be installed in <tt>/tmp/dr/bin/darkradiant</tt>.<br />
<br />
=== Multiprocessor Systems ===<br />
<br />
You can pass the <tt>--jobs=N</tt> parameter to make:<br />
make --jobs=2<br />
to use more than one processor for the compilation. This will eat lots of RAM, so don't do this on machines with little available memory.<br />
<br />
=== Building a .deb package ===<br />
<br />
To build a Debian/Ubuntu package, simply run<br />
<br />
dpkg-buildpackage -rfakeroot<br />
<br />
in the main <tt>darkradiant</tt> directory. The .deb will be created in the parent directory.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&diff=29890DarkRadiant - Compiling in Linux2022-10-02T17:08:44Z<p>Greebo: /* Debian 10 */</p>
<hr />
<div>== Install Required Packages ==<br />
<br />
=== Ubuntu 20.04 and later ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config zlib1g-dev libjpeg-dev libxml2-dev libsigc++-2.0-dev libgtest-dev libeigen3-dev<br />
sudo apt-get install libwxgtk3.0-gtk3-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev libgit2-dev<br />
<br />
=== openSUSE Tumbleweed ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo zypper install git cmake gcc-c++ gettext-tools zlib-devel libjpeg62-devel libxml2-devel libsigc++2-devel gtest<br />
sudo zypper install wxWidgets-3_0-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python38-devel<br />
<br />
=== Mageia 8 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo urpmi git cmake make gcc-c++ libzlib-devel libjpeg-devel libwxgtku3.0-devel libsigc++2.0-devel <br />
sudo urpmi libftgl-devel libglew-devel libpython3-devel libopenal-devel libfreealut-devel libvorbis-devel lib64gtest-devel<br />
<br />
=== Debian 10 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git cmake pkg-config gettext zlib1g-dev libjpeg-dev libwxgtk3.0-dev libgtest-dev libeigen3-dev libgit2-dev<br />
sudo apt-get install libxml2-dev libsigc++-2.0-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== Fedora 26 / 25 ===<br />
Copy and paste the following into a terminal:<br />
<br />
sudo dnf install git automake libtool gcc-c++ zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel libsigc++20-devel <br />
sudo dnf install libpng12-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python-devel pybind11-devel<br />
<br />
Note that the wxGTK package does not yet support Wayland environments, which is the default since Fedora 25 (DarkRadiant will just segfault during startup). You'll need to [https://fedoraproject.org/wiki/Changes/WaylandByDefault deactivate it] for the moment being.<br />
<br />
=== Arch Linux ===<br />
The following packages are required after starting from an Anarchy installation using Gnome as Window Manager. <br />
<br />
sudo pacman -S cmake wxgtk3 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== Manjaro ===<br />
The following packages are required:<br />
sudo pacman -S cmake base-devel wxgtk3 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== CentOS 7 x64 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo yum -y install gcc gcc-c++ git automake libtool zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel <br />
sudo yum -y install libsigc++20-devel ftgl-devel glew-devel boost-devel openal-soft-devel freealut-devel libvorbis-devel python-devel<br />
<br />
CentOS 7 ships with an older compiler, so you'll need to install a more recent GCC first (following the directions on [https://stackoverflow.com/questions/36327805/how-to-install-gcc-5-3-with-yum-on-centos-7-2 stackoverflow]):<br />
<br />
sudo yum install centos-release-scl <br />
sudo yum install devtoolset-4-gcc*<br />
scl enable devtoolset-4 bash<br />
<br />
Note that the <tt>wxGTK3-devel</tt> package doesn't create a <tt>wx-config</tt> symlink in the <tt>/usr/bin</tt> directory, that's why you need to pass an additional <tt>--with-wx-config=/usr/bin/wx-config-3.0</tt> argument to the ./configure script below, like this:<br />
<br />
./configure --enable-darkmod-plugins --with-wx-config=/usr/bin/wx-config-3.0<br />
<br />
=== Slackware 14.2 ===<br />
<br />
Slackware doesn't provide precompiled packages on the one hand (unlike Debian or Arch), but already ships with a lot of libraries on the other. Stuff like git, automake, libtools and development libraries like zlib and boost are already present, but wxWidgets, openAL, ALut and FTGL need to be installed by means of a SlackBuild script. The following has been done in Slackware 14.2, so your mileage may vary.<br />
<br />
Download the Source tarballs and the SlackBuild packages from these URLs:<br />
<br />
* https://slackbuilds.org/repository/14.2/libraries/wxGTK3/<br />
* https://slackbuilds.org/repository/14.2/libraries/ftgl/<br />
* https://slackbuilds.org/repository/14.2/libraries/OpenAL/<br />
* https://slackbuilds.org/repository/14.2/libraries/freealut/<br />
<br />
Download and extract the SlackBuild <tt>.tar.gz</tt> files in your <tt>~/Downloads</tt> folder (or anywhere else where you want to have them). For instance, the wxGTK3 package can be untar'd like this:<br />
<br />
tar xzf wxGTK3.tar.gz<br />
cd wxGTK3<br />
chmod +x wxGTK3.SlackBuild<br />
<br />
Do this for all of the above libraries, that should give you the directories <tt>ftgl/</tt>, <tt>OpenAL/</tt>, <tt>wxGTK3/</tt> and <tt>freealut/</tt>. Next, download the Source Tarballs (the <tt>.tar.bz2</tt>) files from the links above and place them next to the corresponding SlackBuild script. Then run the scripts for each of them and install the build output in your system in a second step:<br />
<br />
./wxGTK3.SlackBuild<br />
<br />
This produced (on my end at least) the package <tt>/tmp/wxGTK3-3.0.2-i486-2_SBo.tgz</tt> which can be installed by the <tt>installpkg</tt> command:<br />
<br />
installpkg /tmp/wxGTK3-3.0.2-i486-2_SBo.tgz<br />
<br />
Do the same for the rest of the libraries (ftgl, OpenAL, freealut). Be aware that the freealut package depends on the OpenAL package, so you need to do the OpenAL one first. Once you have these installed, you can proceed to the build section (<tt>git clone</tt> and <tt>configure</tt> and <tt>make</tt>).<br />
<br />
=== Gentoo ===<br />
<br />
DarkRadiant can be built and installed from an unofficial ebuild repository (overlay). The easiest way to do this is with [https://packages.gentoo.org/packages/app-portage/layman app-portage/layman], which must be installed with the <tt>git</tt> use flag.<br />
<br />
In the 'overlays' section in <tt>/etc/layman/layman.cfg</tt>, add:<br />
<br />
https://raw.githubusercontent.com/varingst/varingst-overlay/master/overlay.xml<br />
<br />
Then fetch and add the overlay:<br />
<br />
# layman -f -a varingst<br />
<br />
Now that the overlay is added, you can build and install DarkRadiant with Portage:<br />
<br />
# emerge darkradiant<br />
<br />
To sync the overlay, either do it manually with layman:<br />
<br />
# layman -s varingst<br />
<br />
Or look into the [https://wiki.gentoo.org/wiki/Project:Portage/Sync various ways to hook into the portage sync system].<br />
<br />
=== Building with a non-default g++ Compiler ===<br />
DarkRadiant's codebase makes use of C++17 features, in particular std::filesystem. Not all distributions ship with a compatible g++ compiler by default, but it's possible to install a more recent compiler suite. Get the compiler package and ensure that the makefiles are called with the correct setup, e.g.<br />
CXX="g++-5.1" cmake . && make && make install<br />
<br />
=== Older Distributions / Compiling DarkRadiant 1.8 and older ===<br />
The instructions about how to compile DR 1.8 (based on GTK) in distributions published in 2012 and older have been removed. They should still be in the [http://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&oldid=18927 history] of this page, should they ever be needed.<br />
<br />
== Obtain the source ==<br />
<br />
Make sure you have the git client installed, this is covered in the package installation commands above. <br />
Next, change to the directory where you want the source code to be in and then clone the Git repository with:<br />
<br />
git clone git://github.com/codereader/DarkRadiant.git --recurse-submodules<br />
<br />
Once the initial clone is done, the source can be updated to the latest version from inside the working directory with:<br />
<br />
git pull<br />
<br />
== Configure and Compile ==<br />
DarkRadiant employs the CMake build system under Linux as used in many open-source projects. Make sure you have the CMake toolchain downloaded, this is covered in the package installation commands above.<br />
<br />
To build DarkRadiant, run the typical chain of CMake and make commands:<br />
<br />
cmake .<br />
make<br />
[sudo] make install<br />
<br />
By the above, a release build will be created; if a debug build is required pass the <tt>-DCMAKE_BUILD_TYPE=Debug</tt> option to the cmake command script.<br />
<br />
Other points to note about the configure process:<br />
<br />
* The DarkMod-specific plugins are built by default, the <tt>-DENABLE_DM_PLUGINS=OFF</tt> argument will disable them.<br />
* The CMake script autodetects required dependencies, and will conditionally enable optional components of DarkRadiant (such as the sound plugin) based on what it finds.<br />
* For quick testing of a DarkRadiant build, it is desirable to install it into a temporary location rather than the default of <tt>/usr/local</tt>; for this, simply pass a prefix option such as <tt>-DCMAKE_INSTALL_PREFIX=/tmp/dr</tt> to cmake, after which DarkRadiant will be installed in <tt>/tmp/dr/bin/darkradiant</tt>.<br />
<br />
=== Multiprocessor Systems ===<br />
<br />
You can pass the <tt>--jobs=N</tt> parameter to make:<br />
make --jobs=2<br />
to use more than one processor for the compilation. This will eat lots of RAM, so don't do this on machines with little available memory.<br />
<br />
=== Building a .deb package ===<br />
<br />
To build a Debian/Ubuntu package, simply run<br />
<br />
dpkg-buildpackage -rfakeroot<br />
<br />
in the main <tt>darkradiant</tt> directory. The .deb will be created in the parent directory.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&diff=29889DarkRadiant - Compiling in Linux2022-10-02T16:52:52Z<p>Greebo: /* Debian 10 */</p>
<hr />
<div>== Install Required Packages ==<br />
<br />
=== Ubuntu 20.04 and later ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config zlib1g-dev libjpeg-dev libxml2-dev libsigc++-2.0-dev libgtest-dev libeigen3-dev<br />
sudo apt-get install libwxgtk3.0-gtk3-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev libgit2-dev<br />
<br />
=== openSUSE Tumbleweed ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo zypper install git cmake gcc-c++ gettext-tools zlib-devel libjpeg62-devel libxml2-devel libsigc++2-devel gtest<br />
sudo zypper install wxWidgets-3_0-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python38-devel<br />
<br />
=== Mageia 8 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo urpmi git cmake make gcc-c++ libzlib-devel libjpeg-devel libwxgtku3.0-devel libsigc++2.0-devel <br />
sudo urpmi libftgl-devel libglew-devel libpython3-devel libopenal-devel libfreealut-devel libvorbis-devel lib64gtest-devel<br />
<br />
=== Debian 10 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git cmake pkg-config gettext zlib1g-dev libjpeg-dev libwxgtk3.0-dev libgtest-dev libeigen3-dev<br />
sudo apt-get install libxml2-dev libsigc++-2.0-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== Fedora 26 / 25 ===<br />
Copy and paste the following into a terminal:<br />
<br />
sudo dnf install git automake libtool gcc-c++ zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel libsigc++20-devel <br />
sudo dnf install libpng12-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python-devel pybind11-devel<br />
<br />
Note that the wxGTK package does not yet support Wayland environments, which is the default since Fedora 25 (DarkRadiant will just segfault during startup). You'll need to [https://fedoraproject.org/wiki/Changes/WaylandByDefault deactivate it] for the moment being.<br />
<br />
=== Arch Linux ===<br />
The following packages are required after starting from an Anarchy installation using Gnome as Window Manager. <br />
<br />
sudo pacman -S cmake wxgtk3 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== Manjaro ===<br />
The following packages are required:<br />
sudo pacman -S cmake base-devel wxgtk3 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== CentOS 7 x64 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo yum -y install gcc gcc-c++ git automake libtool zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel <br />
sudo yum -y install libsigc++20-devel ftgl-devel glew-devel boost-devel openal-soft-devel freealut-devel libvorbis-devel python-devel<br />
<br />
CentOS 7 ships with an older compiler, so you'll need to install a more recent GCC first (following the directions on [https://stackoverflow.com/questions/36327805/how-to-install-gcc-5-3-with-yum-on-centos-7-2 stackoverflow]):<br />
<br />
sudo yum install centos-release-scl <br />
sudo yum install devtoolset-4-gcc*<br />
scl enable devtoolset-4 bash<br />
<br />
Note that the <tt>wxGTK3-devel</tt> package doesn't create a <tt>wx-config</tt> symlink in the <tt>/usr/bin</tt> directory, that's why you need to pass an additional <tt>--with-wx-config=/usr/bin/wx-config-3.0</tt> argument to the ./configure script below, like this:<br />
<br />
./configure --enable-darkmod-plugins --with-wx-config=/usr/bin/wx-config-3.0<br />
<br />
=== Slackware 14.2 ===<br />
<br />
Slackware doesn't provide precompiled packages on the one hand (unlike Debian or Arch), but already ships with a lot of libraries on the other. Stuff like git, automake, libtools and development libraries like zlib and boost are already present, but wxWidgets, openAL, ALut and FTGL need to be installed by means of a SlackBuild script. The following has been done in Slackware 14.2, so your mileage may vary.<br />
<br />
Download the Source tarballs and the SlackBuild packages from these URLs:<br />
<br />
* https://slackbuilds.org/repository/14.2/libraries/wxGTK3/<br />
* https://slackbuilds.org/repository/14.2/libraries/ftgl/<br />
* https://slackbuilds.org/repository/14.2/libraries/OpenAL/<br />
* https://slackbuilds.org/repository/14.2/libraries/freealut/<br />
<br />
Download and extract the SlackBuild <tt>.tar.gz</tt> files in your <tt>~/Downloads</tt> folder (or anywhere else where you want to have them). For instance, the wxGTK3 package can be untar'd like this:<br />
<br />
tar xzf wxGTK3.tar.gz<br />
cd wxGTK3<br />
chmod +x wxGTK3.SlackBuild<br />
<br />
Do this for all of the above libraries, that should give you the directories <tt>ftgl/</tt>, <tt>OpenAL/</tt>, <tt>wxGTK3/</tt> and <tt>freealut/</tt>. Next, download the Source Tarballs (the <tt>.tar.bz2</tt>) files from the links above and place them next to the corresponding SlackBuild script. Then run the scripts for each of them and install the build output in your system in a second step:<br />
<br />
./wxGTK3.SlackBuild<br />
<br />
This produced (on my end at least) the package <tt>/tmp/wxGTK3-3.0.2-i486-2_SBo.tgz</tt> which can be installed by the <tt>installpkg</tt> command:<br />
<br />
installpkg /tmp/wxGTK3-3.0.2-i486-2_SBo.tgz<br />
<br />
Do the same for the rest of the libraries (ftgl, OpenAL, freealut). Be aware that the freealut package depends on the OpenAL package, so you need to do the OpenAL one first. Once you have these installed, you can proceed to the build section (<tt>git clone</tt> and <tt>configure</tt> and <tt>make</tt>).<br />
<br />
=== Gentoo ===<br />
<br />
DarkRadiant can be built and installed from an unofficial ebuild repository (overlay). The easiest way to do this is with [https://packages.gentoo.org/packages/app-portage/layman app-portage/layman], which must be installed with the <tt>git</tt> use flag.<br />
<br />
In the 'overlays' section in <tt>/etc/layman/layman.cfg</tt>, add:<br />
<br />
https://raw.githubusercontent.com/varingst/varingst-overlay/master/overlay.xml<br />
<br />
Then fetch and add the overlay:<br />
<br />
# layman -f -a varingst<br />
<br />
Now that the overlay is added, you can build and install DarkRadiant with Portage:<br />
<br />
# emerge darkradiant<br />
<br />
To sync the overlay, either do it manually with layman:<br />
<br />
# layman -s varingst<br />
<br />
Or look into the [https://wiki.gentoo.org/wiki/Project:Portage/Sync various ways to hook into the portage sync system].<br />
<br />
=== Building with a non-default g++ Compiler ===<br />
DarkRadiant's codebase makes use of C++17 features, in particular std::filesystem. Not all distributions ship with a compatible g++ compiler by default, but it's possible to install a more recent compiler suite. Get the compiler package and ensure that the makefiles are called with the correct setup, e.g.<br />
CXX="g++-5.1" cmake . && make && make install<br />
<br />
=== Older Distributions / Compiling DarkRadiant 1.8 and older ===<br />
The instructions about how to compile DR 1.8 (based on GTK) in distributions published in 2012 and older have been removed. They should still be in the [http://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&oldid=18927 history] of this page, should they ever be needed.<br />
<br />
== Obtain the source ==<br />
<br />
Make sure you have the git client installed, this is covered in the package installation commands above. <br />
Next, change to the directory where you want the source code to be in and then clone the Git repository with:<br />
<br />
git clone git://github.com/codereader/DarkRadiant.git --recurse-submodules<br />
<br />
Once the initial clone is done, the source can be updated to the latest version from inside the working directory with:<br />
<br />
git pull<br />
<br />
== Configure and Compile ==<br />
DarkRadiant employs the CMake build system under Linux as used in many open-source projects. Make sure you have the CMake toolchain downloaded, this is covered in the package installation commands above.<br />
<br />
To build DarkRadiant, run the typical chain of CMake and make commands:<br />
<br />
cmake .<br />
make<br />
[sudo] make install<br />
<br />
By the above, a release build will be created; if a debug build is required pass the <tt>-DCMAKE_BUILD_TYPE=Debug</tt> option to the cmake command script.<br />
<br />
Other points to note about the configure process:<br />
<br />
* The DarkMod-specific plugins are built by default, the <tt>-DENABLE_DM_PLUGINS=OFF</tt> argument will disable them.<br />
* The CMake script autodetects required dependencies, and will conditionally enable optional components of DarkRadiant (such as the sound plugin) based on what it finds.<br />
* For quick testing of a DarkRadiant build, it is desirable to install it into a temporary location rather than the default of <tt>/usr/local</tt>; for this, simply pass a prefix option such as <tt>-DCMAKE_INSTALL_PREFIX=/tmp/dr</tt> to cmake, after which DarkRadiant will be installed in <tt>/tmp/dr/bin/darkradiant</tt>.<br />
<br />
=== Multiprocessor Systems ===<br />
<br />
You can pass the <tt>--jobs=N</tt> parameter to make:<br />
make --jobs=2<br />
to use more than one processor for the compilation. This will eat lots of RAM, so don't do this on machines with little available memory.<br />
<br />
=== Building a .deb package ===<br />
<br />
To build a Debian/Ubuntu package, simply run<br />
<br />
dpkg-buildpackage -rfakeroot<br />
<br />
in the main <tt>darkradiant</tt> directory. The .deb will be created in the parent directory.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&diff=29868DarkRadiant - Compiling in Linux2022-09-23T16:42:43Z<p>Greebo: Manjaro</p>
<hr />
<div>== Install Required Packages ==<br />
<br />
=== Ubuntu 20.04 and later ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config zlib1g-dev libjpeg-dev libxml2-dev libsigc++-2.0-dev libgtest-dev libeigen3-dev<br />
sudo apt-get install libwxgtk3.0-gtk3-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev libgit2-dev<br />
<br />
=== openSUSE Tumbleweed ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo zypper install git cmake gcc-c++ gettext-tools zlib-devel libjpeg62-devel libxml2-devel libsigc++2-devel gtest<br />
sudo zypper install wxWidgets-3_0-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python38-devel<br />
<br />
=== Mageia 8 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo urpmi git cmake make gcc-c++ libzlib-devel libjpeg-devel libwxgtku3.0-devel libsigc++2.0-devel <br />
sudo urpmi libftgl-devel libglew-devel libpython3-devel libopenal-devel libfreealut-devel libvorbis-devel lib64gtest-devel<br />
<br />
=== Debian 10 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git cmake pkg-config gettext zlib1g-dev libjpeg-dev libwxgtk3.0-dev libgtest-dev<br />
sudo apt-get install libxml2-dev libsigc++-2.0-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== Fedora 26 / 25 ===<br />
Copy and paste the following into a terminal:<br />
<br />
sudo dnf install git automake libtool gcc-c++ zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel libsigc++20-devel <br />
sudo dnf install libpng12-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python-devel pybind11-devel<br />
<br />
Note that the wxGTK package does not yet support Wayland environments, which is the default since Fedora 25 (DarkRadiant will just segfault during startup). You'll need to [https://fedoraproject.org/wiki/Changes/WaylandByDefault deactivate it] for the moment being.<br />
<br />
=== Arch Linux ===<br />
The following packages are required after starting from an Anarchy installation using Gnome as Window Manager. <br />
<br />
sudo pacman -S cmake wxgtk3 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== Manjaro ===<br />
The following packages are required:<br />
sudo pacman -S cmake base-devel wxgtk3 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== CentOS 7 x64 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo yum -y install gcc gcc-c++ git automake libtool zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel <br />
sudo yum -y install libsigc++20-devel ftgl-devel glew-devel boost-devel openal-soft-devel freealut-devel libvorbis-devel python-devel<br />
<br />
CentOS 7 ships with an older compiler, so you'll need to install a more recent GCC first (following the directions on [https://stackoverflow.com/questions/36327805/how-to-install-gcc-5-3-with-yum-on-centos-7-2 stackoverflow]):<br />
<br />
sudo yum install centos-release-scl <br />
sudo yum install devtoolset-4-gcc*<br />
scl enable devtoolset-4 bash<br />
<br />
Note that the <tt>wxGTK3-devel</tt> package doesn't create a <tt>wx-config</tt> symlink in the <tt>/usr/bin</tt> directory, that's why you need to pass an additional <tt>--with-wx-config=/usr/bin/wx-config-3.0</tt> argument to the ./configure script below, like this:<br />
<br />
./configure --enable-darkmod-plugins --with-wx-config=/usr/bin/wx-config-3.0<br />
<br />
=== Slackware 14.2 ===<br />
<br />
Slackware doesn't provide precompiled packages on the one hand (unlike Debian or Arch), but already ships with a lot of libraries on the other. Stuff like git, automake, libtools and development libraries like zlib and boost are already present, but wxWidgets, openAL, ALut and FTGL need to be installed by means of a SlackBuild script. The following has been done in Slackware 14.2, so your mileage may vary.<br />
<br />
Download the Source tarballs and the SlackBuild packages from these URLs:<br />
<br />
* https://slackbuilds.org/repository/14.2/libraries/wxGTK3/<br />
* https://slackbuilds.org/repository/14.2/libraries/ftgl/<br />
* https://slackbuilds.org/repository/14.2/libraries/OpenAL/<br />
* https://slackbuilds.org/repository/14.2/libraries/freealut/<br />
<br />
Download and extract the SlackBuild <tt>.tar.gz</tt> files in your <tt>~/Downloads</tt> folder (or anywhere else where you want to have them). For instance, the wxGTK3 package can be untar'd like this:<br />
<br />
tar xzf wxGTK3.tar.gz<br />
cd wxGTK3<br />
chmod +x wxGTK3.SlackBuild<br />
<br />
Do this for all of the above libraries, that should give you the directories <tt>ftgl/</tt>, <tt>OpenAL/</tt>, <tt>wxGTK3/</tt> and <tt>freealut/</tt>. Next, download the Source Tarballs (the <tt>.tar.bz2</tt>) files from the links above and place them next to the corresponding SlackBuild script. Then run the scripts for each of them and install the build output in your system in a second step:<br />
<br />
./wxGTK3.SlackBuild<br />
<br />
This produced (on my end at least) the package <tt>/tmp/wxGTK3-3.0.2-i486-2_SBo.tgz</tt> which can be installed by the <tt>installpkg</tt> command:<br />
<br />
installpkg /tmp/wxGTK3-3.0.2-i486-2_SBo.tgz<br />
<br />
Do the same for the rest of the libraries (ftgl, OpenAL, freealut). Be aware that the freealut package depends on the OpenAL package, so you need to do the OpenAL one first. Once you have these installed, you can proceed to the build section (<tt>git clone</tt> and <tt>configure</tt> and <tt>make</tt>).<br />
<br />
=== Gentoo ===<br />
<br />
DarkRadiant can be built and installed from an unofficial ebuild repository (overlay). The easiest way to do this is with [https://packages.gentoo.org/packages/app-portage/layman app-portage/layman], which must be installed with the <tt>git</tt> use flag.<br />
<br />
In the 'overlays' section in <tt>/etc/layman/layman.cfg</tt>, add:<br />
<br />
https://raw.githubusercontent.com/varingst/varingst-overlay/master/overlay.xml<br />
<br />
Then fetch and add the overlay:<br />
<br />
# layman -f -a varingst<br />
<br />
Now that the overlay is added, you can build and install DarkRadiant with Portage:<br />
<br />
# emerge darkradiant<br />
<br />
To sync the overlay, either do it manually with layman:<br />
<br />
# layman -s varingst<br />
<br />
Or look into the [https://wiki.gentoo.org/wiki/Project:Portage/Sync various ways to hook into the portage sync system].<br />
<br />
=== Building with a non-default g++ Compiler ===<br />
DarkRadiant's codebase makes use of C++17 features, in particular std::filesystem. Not all distributions ship with a compatible g++ compiler by default, but it's possible to install a more recent compiler suite. Get the compiler package and ensure that the makefiles are called with the correct setup, e.g.<br />
CXX="g++-5.1" cmake . && make && make install<br />
<br />
=== Older Distributions / Compiling DarkRadiant 1.8 and older ===<br />
The instructions about how to compile DR 1.8 (based on GTK) in distributions published in 2012 and older have been removed. They should still be in the [http://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&oldid=18927 history] of this page, should they ever be needed.<br />
<br />
== Obtain the source ==<br />
<br />
Make sure you have the git client installed, this is covered in the package installation commands above. <br />
Next, change to the directory where you want the source code to be in and then clone the Git repository with:<br />
<br />
git clone git://github.com/codereader/DarkRadiant.git --recurse-submodules<br />
<br />
Once the initial clone is done, the source can be updated to the latest version from inside the working directory with:<br />
<br />
git pull<br />
<br />
== Configure and Compile ==<br />
DarkRadiant employs the CMake build system under Linux as used in many open-source projects. Make sure you have the CMake toolchain downloaded, this is covered in the package installation commands above.<br />
<br />
To build DarkRadiant, run the typical chain of CMake and make commands:<br />
<br />
cmake .<br />
make<br />
[sudo] make install<br />
<br />
By the above, a release build will be created; if a debug build is required pass the <tt>-DCMAKE_BUILD_TYPE=Debug</tt> option to the cmake command script.<br />
<br />
Other points to note about the configure process:<br />
<br />
* The DarkMod-specific plugins are built by default, the <tt>-DENABLE_DM_PLUGINS=OFF</tt> argument will disable them.<br />
* The CMake script autodetects required dependencies, and will conditionally enable optional components of DarkRadiant (such as the sound plugin) based on what it finds.<br />
* For quick testing of a DarkRadiant build, it is desirable to install it into a temporary location rather than the default of <tt>/usr/local</tt>; for this, simply pass a prefix option such as <tt>-DCMAKE_INSTALL_PREFIX=/tmp/dr</tt> to cmake, after which DarkRadiant will be installed in <tt>/tmp/dr/bin/darkradiant</tt>.<br />
<br />
=== Multiprocessor Systems ===<br />
<br />
You can pass the <tt>--jobs=N</tt> parameter to make:<br />
make --jobs=2<br />
to use more than one processor for the compilation. This will eat lots of RAM, so don't do this on machines with little available memory.<br />
<br />
=== Building a .deb package ===<br />
<br />
To build a Debian/Ubuntu package, simply run<br />
<br />
dpkg-buildpackage -rfakeroot<br />
<br />
in the main <tt>darkradiant</tt> directory. The .deb will be created in the parent directory.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=29832DarkRadiant Script Reference2022-09-07T10:51:59Z<p>Greebo: </p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== MeshVertex =====<br />
A MeshVertex 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).<br />
(This type has been named ArbitraryMeshVertex until 2.14.)<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three MeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>MeshVertex a</tt> The first vertex of this polygon<br />
* <tt>MeshVertex b</tt> The second vertex of this polygon<br />
* <tt>MeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== GlobalDeclarationManager ===<br />
The declaration manager (available since 3.1.0) offers methods to interact with the declarations like Materials, Skins, ModelDefs defined throughout the mod. It can iterate through existing declarations, find them, manipulate them and even save them back to disk. See also the [https://github.com/codereader/DarkRadiant/blob/master/install/scripts/test.py Test Python Script] (scripts/test.py) in DarkRadiant's installation location.<br />
<br />
* <tt>Declaration findDeclaration(Declaration.Type type, string name)</tt> Finds a named declaration. If the declaration is not found, a NULL object is returned, see <tt>Declaration.isNull</tt>.<br />
* <tt>Declaration findOrCreateDeclaration(Declaration.Type type, string name)</tt> Finds an existing named declaration or creates an empty one if no declaration with that name exists yet. Will always return a non-null object.<br />
* <tt>Declaration foreachDeclaration(Declaration.Type type, DeclarationVisitor visitor)</tt> Calls the <tt>visit</tt> method of the given visitor class, see the example below.<br />
* <tt>bool renameDeclaration(Declaration.Type type, string oldName, string newName)</tt> Renames the declaration from oldName to newName. The new name must not be in use by any other declaration, and it must be different from oldName, otherwise renaming will fail. Returns true if the old declaration existed and could successfully be renamed, false on any failure.<br />
* <tt>removeDeclaration(Declaration.Type type, string name)</tt> Removes the given declaration from the internal dictionaries. This doesn't remove the declaration from the source files, so this operation will not survive a reloadDeclarations command. Used to remove temporary decls in edit scenarios.<br />
* <tt>reloadDeclarations()</tt> Reload all declarations. All declaration references your script may hold will stay intact, only their contents will be refreshed.<br />
* <tt>saveDeclaration(Declaration decl)</tt> Saves the given declaration to a physical declaration file. Depending on the original location of the declaration the outcome will be different (see notes below).<br />
<br />
'''Notes on saveDeclaration'''<br />
<br />
It is required for the declaration to have valid file information set on its syntax block, otherwise the declaration manager will not know where to save it to.<br />
* Case #1: Newly created declarations (created through findOrCreateDeclaration): The decl will be appended to the given file. The file will be created if required.<br />
* Case #2: Existing declarations (with their original file being a physical file): The decl in the file will be replaced with its new syntax block. All the content before and after the declaration will be left untouched.<br />
* Case #3: Existing declarations (with their original file being stored within a PK4): The decl file will be copied and saved to its corresponding physical location, effectively creating a file that will override the one in the PK4. The decl will be merged into the file just like in case #2<br />
<br />
==== Declaration.Type ====<br />
An enumeration of the available decl types supported by DarkRadiant:<br />
* Declaration.Type.'''Material'''<br />
* Declaration.Type.'''Table'''<br />
* Declaration.Type.'''EntityDef'''<br />
* Declaration.Type.'''SoundShader'''<br />
* Declaration.Type.'''ModelDef'''<br />
* Declaration.Type.'''Particle'''<br />
* Declaration.Type.'''Skin'''<br />
<br />
==== Declaration ====<br />
Represents a generic declaration as defined in the .mtr, .skin and .def files throughout the active mod or mission project.<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through DeclarationManager.findDeclaration<br />
* <tt>string getDeclName()</tt> Returns the name of this declaration, e.g. "textures/common/caulk"<br />
* <tt>Type getDeclType()</tt> Returns the declaration type, e.g. Declaration.Type.Skin<br />
* <tt>DeclarationBlockSyntax getBlockSyntax()</tt> Returns the syntax block containing the raw source text<br />
* <tt>setBlockSyntax(DeclarationBlockSyntax syntax)</tt> Assigns a new syntax block to this declaration<br />
* <tt>string getDeclFilePath()</tt> Returns the mod-relative path of the file this declaration has been defined in (e.g. "materials/test.mtr")<br />
* <tt>setDeclFilePath(string folder, string filename)</tt> Sets the mod-relative folder and filename of this declaration (useful right before saving a newly created declaration), Example: setDeclFilePath("materials/", "test.mtr")<br />
<br />
==== DeclarationBlockSyntax ====<br />
The syntax block contains the raw text contents as found in the file the declaration was defined in. The <tt>contents</tt> property holds the source text excluding the name and the outermost surrounding curly braces, so only the inner part is stored here. It can be modified and saved back into a declaration using <tt>setBlockSyntax</tt>.<br />
* <tt>typeName</tt> Returns typename as defined in the source file (can also be empty if none was specified)<br />
* <tt>name</tt> Returns the name of this block<br />
* <tt>contents</tt> Returns the raw contents of this block, excluding the name and the outermost surrounding curly braces<br />
* <tt>modName</tt> Returns the name of the mod/FM/project this block has been declared in.<br />
<br />
==== DeclarationVisitor ====<br />
A DeclarationVisitor can be used to iterate over all existing declarations of a given type. It just needs a single method definition named visit:<br />
* <tt>visit(Declaration decl)</tt> Is called for each known Declaration.<br />
<br />
This code example can be used as template when writing scripts for declarations; it shows how to print the name and filename of each skin declaration:<br />
import darkradiant as dr<br />
<br />
# Test implementing a DeclarationManager interface<br />
class TestDeclarationVisitor(dr.DeclarationVisitor) :<br />
def visit(self, decl):<br />
print(str(decl.getDeclType()) + ": " + decl.getDeclName() + " defined in " + decl.getDeclFilePath())<br />
<br />
visitor= TestDeclarationVisitor()<br />
GlobalDeclarationManager.foreachDeclaration(Declaration.Type.Skin, visitor)<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
=== GlobalFxManager ===<br />
The FX manager (available since 3.3.0) exposes methods to interact with FX declarations.<br />
<br />
* <tt>FxDeclaration findFx(string name)</tt> Finds a named FX declaration. If the declaration is not found, a NULL object is returned, see <tt>FxDeclaration.isNull</tt>.<br />
<br />
Example code: <br />
fx = GlobalFxManager.findFx("fx/sparks")<br />
<br />
if not fx.isNull:<br />
print(fx.getDeclName())<br />
<br />
==== FxDeclaration ====<br />
Represents an FX declaration as defined in the .fx file. It inherits all methods from a generic '''Declaration''' object (see DeclarationManager interface).<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through GlobalFxManager.findFx<br />
* <tt>string getBindTo()</tt> Returns the name of this declaration, e.g. "fx/sparks"<br />
* <tt>int getNumActions()</tt> Returns the number of actions defined in this effect.<br />
* <tt>FxAction getAction(int index)</tt> Returns the i-th action (index is starting with 0)<br />
<br />
==== FxAction ====<br />
The FxAction object offers methods to check the various values set on a single action block.<br />
* <tt>FxAction.Type getActionType()</tt> Returns the type of this action, see '''FxAction.Type''' below.<br />
* <tt>string getName()</tt> Returns the name of this action (which might be an empty string)<br />
* <tt>float getDelayInSeconds()</tt> Returns the action delay in seconds<br />
* <tt>float getDurationInSeconds()</tt> Action duration in seconds, before it is killed or restarted<br />
* <tt>bool getIgnoreMaster()</tt> True: Don't shake the entity this effect is attached to<br />
* <tt>float getShakeTimeInSeconds()</tt> Shake parameter<br />
* <tt>float getShakeAmplitude()</tt> Shake parameter<br />
* <tt>float getShakeDistance()</tt> Shake parameter<br />
* <tt>bool getShakeFalloff()</tt> Shake parameter<br />
* <tt>float getShakeImpulse()</tt> Shake parameter<br />
* <tt>bool getNoShadows()</tt> if this is 1, the light in this effect doesn't cast shadows<br />
* <tt>string getFireSiblingAction()</tt> Causes the sibling action to happen when this action does<br />
* <tt>float getRandomDelay()</tt> Let the delay be random between min and max (in seconds). If both are 0.0 no random delay is active and the regular delay is used instead<br />
* <tt>float getRotate()</tt> According to the docs this is not used<br />
* <tt>bool getTrackOrigin()</tt> Move around with the entity (vs stationary after spawning)<br />
* <tt>bool getRestart()</tt> If this is 1, the action starts again after the 'duration' has run out<br />
* <tt>float getFadeInTimeInSeconds()</tt> Fade in the RGB of the light or model over <time> seconds<br />
* <tt>float getFadeOutTimeInSeconds()</tt> Fade out the light/model. Ignored if fadeIn is set, you can use 2 separate actions (tied together with uselight) if you want a light to fade in and out.<br />
* <tt>float getDecalSize()</tt> Size of the decal (corresponds to "size" keyword)<br />
* <tt>Vector3 getOffset()</tt> Offset from the origin of the entity (or bind point) this action is located at<br />
* <tt>Vector3 getAxis()</tt> Axis of the model, mutually exclusive with angle<br />
* <tt>Vector3 getAngle()</tt> Alternate way of setting the axis of the model<br />
* <tt>string getUseLight()</tt> Returns the name of the action containing the light which should be used<br />
* <tt>string getUseModel()</tt> Modify the model in a named sibling action. Can be used to fade out a particle in a sibling.<br />
* <tt>string getAttachLight()</tt> Attach to external light (a light not defined in the effect) for fading.<br />
* <tt>string getAttachEntity()</tt> Attach to an external entity<br />
* <tt>string getLaunchProjectileDef()</tt> Launches a projectile of the given entityDef<br />
* <tt>string getLightMaterialName()</tt> If not empty, this action spawns a light with this material<br />
* <tt>Vector3 getLightRgbColour()</tt> For FxAction.Type.Light actions, this defines the RGB colour components<br />
* <tt>float getLightRadius()</tt> For FxAction.Type.Light actions, this defines the radius of the spawned light<br />
* <tt>string getModelName()</tt> Return the name of the model or particle<br />
* <tt>string getDecalMaterialName()</tt> For FxAction.Type.Decal actions, this defines the decal material name<br />
* <tt>bool getParticleTrackVelocity()</tt> Unused according to docs<br />
* <tt>string getSoundShaderName()</tt> For FxAction.Type.:Sound actions: start a sound (on any channel)<br />
* <tt>string getShockwaveDefName()</tt> For FxAction.Type.Shockwave actions: the name of the shockwave entityDef<br />
<br />
==== FxAction.Type ====<br />
An enumeration of the available FX action types known to DarkRadiant:<br />
* FxAction.Type.'''Undefined'''<br />
* FxAction.Type.'''Light'''<br />
* FxAction.Type.'''Particle'''<br />
* FxAction.Type.'''Decal'''<br />
* FxAction.Type.'''Model'''<br />
* FxAction.Type.'''Sound'''<br />
* FxAction.Type.'''Shake'''<br />
* FxAction.Type.'''AttachLight'''<br />
* FxAction.Type.'''AttachEntity'''<br />
* FxAction.Type.'''Launch'''<br />
* FxAction.Type.'''Shockwave'''<br />
<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&diff=29811DarkRadiant - Compiling in Linux2022-08-26T06:41:03Z<p>Greebo: /* Arch Linux */</p>
<hr />
<div>== Install Required Packages ==<br />
<br />
=== Ubuntu 20.04 and later ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config zlib1g-dev libjpeg-dev libxml2-dev libsigc++-2.0-dev libgtest-dev libeigen3-dev<br />
sudo apt-get install libwxgtk3.0-gtk3-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev libgit2-dev<br />
<br />
=== openSUSE Tumbleweed ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo zypper install git cmake gcc-c++ gettext-tools zlib-devel libjpeg62-devel libxml2-devel libsigc++2-devel gtest<br />
sudo zypper install wxWidgets-3_0-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python38-devel<br />
<br />
=== Mageia 8 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo urpmi git cmake make gcc-c++ libzlib-devel libjpeg-devel libwxgtku3.0-devel libsigc++2.0-devel <br />
sudo urpmi libftgl-devel libglew-devel libpython3-devel libopenal-devel libfreealut-devel libvorbis-devel lib64gtest-devel<br />
<br />
=== Debian 10 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git cmake pkg-config gettext zlib1g-dev libjpeg-dev libwxgtk3.0-dev libgtest-dev<br />
sudo apt-get install libxml2-dev libsigc++-2.0-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== Fedora 26 / 25 ===<br />
Copy and paste the following into a terminal:<br />
<br />
sudo dnf install git automake libtool gcc-c++ zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel libsigc++20-devel <br />
sudo dnf install libpng12-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python-devel pybind11-devel<br />
<br />
Note that the wxGTK package does not yet support Wayland environments, which is the default since Fedora 25 (DarkRadiant will just segfault during startup). You'll need to [https://fedoraproject.org/wiki/Changes/WaylandByDefault deactivate it] for the moment being.<br />
<br />
=== Arch Linux ===<br />
The following packages are requred after starting from an Anarchy installation using Gnome as Window Manager. <br />
<br />
sudo pacman -S cmake wxgtk3 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== CentOS 7 x64 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo yum -y install gcc gcc-c++ git automake libtool zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel <br />
sudo yum -y install libsigc++20-devel ftgl-devel glew-devel boost-devel openal-soft-devel freealut-devel libvorbis-devel python-devel<br />
<br />
CentOS 7 ships with an older compiler, so you'll need to install a more recent GCC first (following the directions on [https://stackoverflow.com/questions/36327805/how-to-install-gcc-5-3-with-yum-on-centos-7-2 stackoverflow]):<br />
<br />
sudo yum install centos-release-scl <br />
sudo yum install devtoolset-4-gcc*<br />
scl enable devtoolset-4 bash<br />
<br />
Note that the <tt>wxGTK3-devel</tt> package doesn't create a <tt>wx-config</tt> symlink in the <tt>/usr/bin</tt> directory, that's why you need to pass an additional <tt>--with-wx-config=/usr/bin/wx-config-3.0</tt> argument to the ./configure script below, like this:<br />
<br />
./configure --enable-darkmod-plugins --with-wx-config=/usr/bin/wx-config-3.0<br />
<br />
=== Slackware 14.2 ===<br />
<br />
Slackware doesn't provide precompiled packages on the one hand (unlike Debian or Arch), but already ships with a lot of libraries on the other. Stuff like git, automake, libtools and development libraries like zlib and boost are already present, but wxWidgets, openAL, ALut and FTGL need to be installed by means of a SlackBuild script. The following has been done in Slackware 14.2, so your mileage may vary.<br />
<br />
Download the Source tarballs and the SlackBuild packages from these URLs:<br />
<br />
* https://slackbuilds.org/repository/14.2/libraries/wxGTK3/<br />
* https://slackbuilds.org/repository/14.2/libraries/ftgl/<br />
* https://slackbuilds.org/repository/14.2/libraries/OpenAL/<br />
* https://slackbuilds.org/repository/14.2/libraries/freealut/<br />
<br />
Download and extract the SlackBuild <tt>.tar.gz</tt> files in your <tt>~/Downloads</tt> folder (or anywhere else where you want to have them). For instance, the wxGTK3 package can be untar'd like this:<br />
<br />
tar xzf wxGTK3.tar.gz<br />
cd wxGTK3<br />
chmod +x wxGTK3.SlackBuild<br />
<br />
Do this for all of the above libraries, that should give you the directories <tt>ftgl/</tt>, <tt>OpenAL/</tt>, <tt>wxGTK3/</tt> and <tt>freealut/</tt>. Next, download the Source Tarballs (the <tt>.tar.bz2</tt>) files from the links above and place them next to the corresponding SlackBuild script. Then run the scripts for each of them and install the build output in your system in a second step:<br />
<br />
./wxGTK3.SlackBuild<br />
<br />
This produced (on my end at least) the package <tt>/tmp/wxGTK3-3.0.2-i486-2_SBo.tgz</tt> which can be installed by the <tt>installpkg</tt> command:<br />
<br />
installpkg /tmp/wxGTK3-3.0.2-i486-2_SBo.tgz<br />
<br />
Do the same for the rest of the libraries (ftgl, OpenAL, freealut). Be aware that the freealut package depends on the OpenAL package, so you need to do the OpenAL one first. Once you have these installed, you can proceed to the build section (<tt>git clone</tt> and <tt>configure</tt> and <tt>make</tt>).<br />
<br />
=== Gentoo ===<br />
<br />
DarkRadiant can be built and installed from an unofficial ebuild repository (overlay). The easiest way to do this is with [https://packages.gentoo.org/packages/app-portage/layman app-portage/layman], which must be installed with the <tt>git</tt> use flag.<br />
<br />
In the 'overlays' section in <tt>/etc/layman/layman.cfg</tt>, add:<br />
<br />
https://raw.githubusercontent.com/varingst/varingst-overlay/master/overlay.xml<br />
<br />
Then fetch and add the overlay:<br />
<br />
# layman -f -a varingst<br />
<br />
Now that the overlay is added, you can build and install DarkRadiant with Portage:<br />
<br />
# emerge darkradiant<br />
<br />
To sync the overlay, either do it manually with layman:<br />
<br />
# layman -s varingst<br />
<br />
Or look into the [https://wiki.gentoo.org/wiki/Project:Portage/Sync various ways to hook into the portage sync system].<br />
<br />
=== Building with a non-default g++ Compiler ===<br />
DarkRadiant's codebase makes use of C++17 features, in particular std::filesystem. Not all distributions ship with a compatible g++ compiler by default, but it's possible to install a more recent compiler suite. Get the compiler package and ensure that the makefiles are called with the correct setup, e.g.<br />
CXX="g++-5.1" cmake . && make && make install<br />
<br />
=== Older Distributions / Compiling DarkRadiant 1.8 and older ===<br />
The instructions about how to compile DR 1.8 (based on GTK) in distributions published in 2012 and older have been removed. They should still be in the [http://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&oldid=18927 history] of this page, should they ever be needed.<br />
<br />
== Obtain the source ==<br />
<br />
Make sure you have the git client installed, this is covered in the package installation commands above. <br />
Next, change to the directory where you want the source code to be in and then clone the Git repository with:<br />
<br />
git clone git://github.com/codereader/DarkRadiant.git --recurse-submodules<br />
<br />
Once the initial clone is done, the source can be updated to the latest version from inside the working directory with:<br />
<br />
git pull<br />
<br />
== Configure and Compile ==<br />
DarkRadiant employs the CMake build system under Linux as used in many open-source projects. Make sure you have the CMake toolchain downloaded, this is covered in the package installation commands above.<br />
<br />
To build DarkRadiant, run the typical chain of CMake and make commands:<br />
<br />
cmake .<br />
make<br />
[sudo] make install<br />
<br />
By the above, a release build will be created; if a debug build is required pass the <tt>-DCMAKE_BUILD_TYPE=Debug</tt> option to the cmake command script.<br />
<br />
Other points to note about the configure process:<br />
<br />
* The DarkMod-specific plugins are built by default, the <tt>-DENABLE_DM_PLUGINS=OFF</tt> argument will disable them.<br />
* The CMake script autodetects required dependencies, and will conditionally enable optional components of DarkRadiant (such as the sound plugin) based on what it finds.<br />
* For quick testing of a DarkRadiant build, it is desirable to install it into a temporary location rather than the default of <tt>/usr/local</tt>; for this, simply pass a prefix option such as <tt>-DCMAKE_INSTALL_PREFIX=/tmp/dr</tt> to cmake, after which DarkRadiant will be installed in <tt>/tmp/dr/bin/darkradiant</tt>.<br />
<br />
=== Multiprocessor Systems ===<br />
<br />
You can pass the <tt>--jobs=N</tt> parameter to make:<br />
make --jobs=2<br />
to use more than one processor for the compilation. This will eat lots of RAM, so don't do this on machines with little available memory.<br />
<br />
=== Building a .deb package ===<br />
<br />
To build a Debian/Ubuntu package, simply run<br />
<br />
dpkg-buildpackage -rfakeroot<br />
<br />
in the main <tt>darkradiant</tt> directory. The .deb will be created in the parent directory.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=29744DarkRadiant Script Reference2022-07-28T20:05:59Z<p>Greebo: /* Declaration.Type */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== MeshVertex =====<br />
A MeshVertex 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).<br />
(This type has been named ArbitraryMeshVertex until 2.14.)<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three MeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>MeshVertex a</tt> The first vertex of this polygon<br />
* <tt>MeshVertex b</tt> The second vertex of this polygon<br />
* <tt>MeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== GlobalDeclarationManager ===<br />
The declaration manager (available since 3.1.0) offers methods to interact with the declarations like Materials, Skins, ModelDefs defined throughout the mod. It can iterate through existing declarations, find them, manipulate them and even save them back to disk. See also the [https://github.com/codereader/DarkRadiant/blob/master/install/scripts/test.py Test Python Script] (scripts/test.py) in DarkRadiant's installation location.<br />
<br />
* <tt>Declaration findDeclaration(Declaration.Type type, string name)</tt> Finds a named declaration. If the declaration is not found, a NULL object is returned, see <tt>Declaration.isNull</tt>.<br />
* <tt>Declaration findOrCreateDeclaration(Declaration.Type type, string name)</tt> Finds an existing named declaration or creates an empty one if no declaration with that name exists yet. Will always return a non-null object.<br />
* <tt>Declaration foreachDeclaration(Declaration.Type type, DeclarationVisitor visitor)</tt> Calls the <tt>visit</tt> method of the given visitor class, see the example below.<br />
* <tt>bool renameDeclaration(Declaration.Type type, string oldName, string newName)</tt> Renames the declaration from oldName to newName. The new name must not be in use by any other declaration, and it must be different from oldName, otherwise renaming will fail. Returns true if the old declaration existed and could successfully be renamed, false on any failure.<br />
* <tt>removeDeclaration(Declaration.Type type, string name)</tt> Removes the given declaration from the internal dictionaries. This doesn't remove the declaration from the source files, so this operation will not survive a reloadDeclarations command. Used to remove temporary decls in edit scenarios.<br />
* <tt>reloadDeclarations()</tt> Reload all declarations. All declaration references your script may hold will stay intact, only their contents will be refreshed.<br />
* <tt>saveDeclaration(Declaration decl)</tt> Saves the given declaration to a physical declaration file. Depending on the original location of the declaration the outcome will be different (see notes below).<br />
<br />
'''Notes on saveDeclaration'''<br />
<br />
It is required for the declaration to have valid file information set on its syntax block, otherwise the declaration manager will not know where to save it to.<br />
* Case #1: Newly created declarations (created through findOrCreateDeclaration): The decl will be appended to the given file. The file will be created if required.<br />
* Case #2: Existing declarations (with their original file being a physical file): The decl in the file will be replaced with its new syntax block. All the content before and after the declaration will be left untouched.<br />
* Case #3: Existing declarations (with their original file being stored within a PK4): The decl file will be copied and saved to its corresponding physical location, effectively creating a file that will override the one in the PK4. The decl will be merged into the file just like in case #2<br />
<br />
==== Declaration.Type ====<br />
An enumeration of the available decl types supported by DarkRadiant:<br />
* Declaration.Type.'''Material'''<br />
* Declaration.Type.'''Table'''<br />
* Declaration.Type.'''EntityDef'''<br />
* Declaration.Type.'''SoundShader'''<br />
* Declaration.Type.'''ModelDef'''<br />
* Declaration.Type.'''Particle'''<br />
* Declaration.Type.'''Skin'''<br />
<br />
==== Declaration ====<br />
Represents a generic declaration as defined in the .mtr, .skin and .def files throughout the active mod or mission project.<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through DeclarationManager.findDeclaration<br />
* <tt>string getDeclName()</tt> Returns the name of this declaration, e.g. "textures/common/caulk"<br />
* <tt>Type getDeclType()</tt> Returns the declaration type, e.g. Declaration.Type.Skin<br />
* <tt>DeclarationBlockSyntax getBlockSyntax()</tt> Returns the syntax block containing the raw source text<br />
* <tt>setBlockSyntax(DeclarationBlockSyntax syntax)</tt> Assigns a new syntax block to this declaration<br />
* <tt>string getDeclFilePath()</tt> Returns the mod-relative path of the file this declaration has been defined in (e.g. "materials/test.mtr")<br />
* <tt>setDeclFilePath(string folder, string filename)</tt> Sets the mod-relative folder and filename of this declaration (useful right before saving a newly created declaration), Example: setDeclFilePath("materials/", "test.mtr")<br />
<br />
==== DeclarationBlockSyntax ====<br />
The syntax block contains the raw text contents as found in the file the declaration was defined in. The <tt>contents</tt> property holds the source text excluding the name and the outermost surrounding curly braces, so only the inner part is stored here. It can be modified and saved back into a declaration using <tt>setBlockSyntax</tt>.<br />
* <tt>typeName</tt> Returns typename as defined in the source file (can also be empty if none was specified)<br />
* <tt>name</tt> Returns the name of this block<br />
* <tt>contents</tt> Returns the raw contents of this block, excluding the name and the outermost surrounding curly braces<br />
* <tt>modName</tt> Returns the name of the mod/FM/project this block has been declared in.<br />
<br />
==== DeclarationVisitor ====<br />
A DeclarationVisitor can be used to iterate over all existing declarations of a given type. It just needs a single method definition named visit:<br />
* <tt>visit(Declaration decl)</tt> Is called for each known Declaration.<br />
<br />
This code example can be used as template when writing scripts for declarations; it shows how to print the name and filename of each skin declaration:<br />
import darkradiant as dr<br />
<br />
# Test implementing a DeclarationManager interface<br />
class TestDeclarationVisitor(dr.DeclarationVisitor) :<br />
def visit(self, decl):<br />
print(str(decl.getDeclType()) + ": " + decl.getDeclName() + " defined in " + decl.getDeclFilePath())<br />
<br />
visitor= TestDeclarationVisitor()<br />
GlobalDeclarationManager.foreachDeclaration(Declaration.Type.Skin, visitor)<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=29743DarkRadiant Script Reference2022-07-28T18:45:05Z<p>Greebo: /* GlobalDeclarationManager */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== MeshVertex =====<br />
A MeshVertex 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).<br />
(This type has been named ArbitraryMeshVertex until 2.14.)<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three MeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>MeshVertex a</tt> The first vertex of this polygon<br />
* <tt>MeshVertex b</tt> The second vertex of this polygon<br />
* <tt>MeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== GlobalDeclarationManager ===<br />
The declaration manager (available since 3.1.0) offers methods to interact with the declarations like Materials, Skins, ModelDefs defined throughout the mod. It can iterate through existing declarations, find them, manipulate them and even save them back to disk. See also the [https://github.com/codereader/DarkRadiant/blob/master/install/scripts/test.py Test Python Script] (scripts/test.py) in DarkRadiant's installation location.<br />
<br />
* <tt>Declaration findDeclaration(Declaration.Type type, string name)</tt> Finds a named declaration. If the declaration is not found, a NULL object is returned, see <tt>Declaration.isNull</tt>.<br />
* <tt>Declaration findOrCreateDeclaration(Declaration.Type type, string name)</tt> Finds an existing named declaration or creates an empty one if no declaration with that name exists yet. Will always return a non-null object.<br />
* <tt>Declaration foreachDeclaration(Declaration.Type type, DeclarationVisitor visitor)</tt> Calls the <tt>visit</tt> method of the given visitor class, see the example below.<br />
* <tt>bool renameDeclaration(Declaration.Type type, string oldName, string newName)</tt> Renames the declaration from oldName to newName. The new name must not be in use by any other declaration, and it must be different from oldName, otherwise renaming will fail. Returns true if the old declaration existed and could successfully be renamed, false on any failure.<br />
* <tt>removeDeclaration(Declaration.Type type, string name)</tt> Removes the given declaration from the internal dictionaries. This doesn't remove the declaration from the source files, so this operation will not survive a reloadDeclarations command. Used to remove temporary decls in edit scenarios.<br />
* <tt>reloadDeclarations()</tt> Reload all declarations. All declaration references your script may hold will stay intact, only their contents will be refreshed.<br />
* <tt>saveDeclaration(Declaration decl)</tt> Saves the given declaration to a physical declaration file. Depending on the original location of the declaration the outcome will be different (see notes below).<br />
<br />
'''Notes on saveDeclaration'''<br />
<br />
It is required for the declaration to have valid file information set on its syntax block, otherwise the declaration manager will not know where to save it to.<br />
* Case #1: Newly created declarations (created through findOrCreateDeclaration): The decl will be appended to the given file. The file will be created if required.<br />
* Case #2: Existing declarations (with their original file being a physical file): The decl in the file will be replaced with its new syntax block. All the content before and after the declaration will be left untouched.<br />
* Case #3: Existing declarations (with their original file being stored within a PK4): The decl file will be copied and saved to its corresponding physical location, effectively creating a file that will override the one in the PK4. The decl will be merged into the file just like in case #2<br />
<br />
==== Declaration.Type ====<br />
An enumeration of the available decl types supported by DarkRadiant:<br />
* Declaration.Type.'''None'''<br />
* Declaration.Type.'''Material'''<br />
* Declaration.Type.'''Table'''<br />
* Declaration.Type.'''EntityDef'''<br />
* Declaration.Type.'''SoundShader'''<br />
* Declaration.Type.'''ModelDef'''<br />
* Declaration.Type.'''Particle'''<br />
* Declaration.Type.'''Skin'''<br />
<br />
==== Declaration ====<br />
Represents a generic declaration as defined in the .mtr, .skin and .def files throughout the active mod or mission project.<br />
* <tt>bool isNull()</tt> Returns true if this is a NULL object, e.g. if a non-existent declaration has been requested through DeclarationManager.findDeclaration<br />
* <tt>string getDeclName()</tt> Returns the name of this declaration, e.g. "textures/common/caulk"<br />
* <tt>Type getDeclType()</tt> Returns the declaration type, e.g. Declaration.Type.Skin<br />
* <tt>DeclarationBlockSyntax getBlockSyntax()</tt> Returns the syntax block containing the raw source text<br />
* <tt>setBlockSyntax(DeclarationBlockSyntax syntax)</tt> Assigns a new syntax block to this declaration<br />
* <tt>string getDeclFilePath()</tt> Returns the mod-relative path of the file this declaration has been defined in (e.g. "materials/test.mtr")<br />
* <tt>setDeclFilePath(string folder, string filename)</tt> Sets the mod-relative folder and filename of this declaration (useful right before saving a newly created declaration), Example: setDeclFilePath("materials/", "test.mtr")<br />
<br />
==== DeclarationBlockSyntax ====<br />
The syntax block contains the raw text contents as found in the file the declaration was defined in. The <tt>contents</tt> property holds the source text excluding the name and the outermost surrounding curly braces, so only the inner part is stored here. It can be modified and saved back into a declaration using <tt>setBlockSyntax</tt>.<br />
* <tt>typeName</tt> Returns typename as defined in the source file (can also be empty if none was specified)<br />
* <tt>name</tt> Returns the name of this block<br />
* <tt>contents</tt> Returns the raw contents of this block, excluding the name and the outermost surrounding curly braces<br />
* <tt>modName</tt> Returns the name of the mod/FM/project this block has been declared in.<br />
<br />
==== DeclarationVisitor ====<br />
A DeclarationVisitor can be used to iterate over all existing declarations of a given type. It just needs a single method definition named visit:<br />
* <tt>visit(Declaration decl)</tt> Is called for each known Declaration.<br />
<br />
This code example can be used as template when writing scripts for declarations; it shows how to print the name and filename of each skin declaration:<br />
import darkradiant as dr<br />
<br />
# Test implementing a DeclarationManager interface<br />
class TestDeclarationVisitor(dr.DeclarationVisitor) :<br />
def visit(self, decl):<br />
print(str(decl.getDeclType()) + ": " + decl.getDeclName() + " defined in " + decl.getDeclFilePath())<br />
<br />
visitor= TestDeclarationVisitor()<br />
GlobalDeclarationManager.foreachDeclaration(Declaration.Type.Skin, visitor)<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=29742DarkRadiant Script Reference2022-07-28T18:23:17Z<p>Greebo: DeclarationManager interface (WIP)</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== MeshVertex =====<br />
A MeshVertex 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).<br />
(This type has been named ArbitraryMeshVertex until 2.14.)<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three MeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>MeshVertex a</tt> The first vertex of this polygon<br />
* <tt>MeshVertex b</tt> The second vertex of this polygon<br />
* <tt>MeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== GlobalDeclarationManager ===<br />
The global declaration manager offers methods to interact with the declarations like Materials, Skins, ModelDefs defined throughout the mod. It can iterate through existing declarations, find them, manipulate them and even save them back to disk.<br />
This whole interface is available since DarkRadiant 3.1.0.<br />
<br />
* <tt>Declaration findDeclaration(Declaration.Type type, string name)</tt> Finds a named declaration. If the declaration is not found, a NULL object is returned, see <tt>Declaration.isNull</tt>.<br />
* <tt>Declaration findOrCreateDeclaration(Declaration.Type type, string name)</tt> Finds an existing named declaration or creates an empty one if no declaration with that name exists yet. Will always return a non-null object.<br />
* <tt>Declaration foreachDeclaration(Declaration.Type type, DeclarationVisitor visitor)</tt> Calls the <tt>visit</tt> method of the given visitor class, see the example below.<br />
<br />
==== DeclarationVisitor ====<br />
A DeclarationVisitor can be used to iterate over all existing declarations of a given type. It just needs a single function definition named visit:<br />
* <tt>visit(Declaration decl)</tt> Is called for each known Declaration.<br />
<br />
This code example can be used as template when writing scripts for declarations; it shows how to print the name and filename of each skin declaration:<br />
import darkradiant as dr<br />
<br />
# Test implementing a DeclarationManager interface<br />
class TestDeclarationVisitor(dr.DeclarationVisitor) :<br />
def visit(self, decl):<br />
print(str(decl.getDeclType()) + ": " + decl.getDeclName() + " defined in " + decl.getDeclFilePath())<br />
<br />
visitor= TestDeclarationVisitor()<br />
GlobalDeclarationManager.foreachDeclaration(Declaration.Type.Skin, visitor)<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Windows&diff=29452DarkRadiant - Compiling in Windows2022-04-01T19:35:08Z<p>Greebo: </p>
<hr />
<div>To compile the sources in Windows you will need '''Visual Studio 2022 Community Edition''' or higher. The Community Edition can be acquired for free and is able to produce 64 Bit builds. <br />
<br />
You will need a Git client to clone the sources to your machine and install the Windows dependencies package. Then you're set up to compile DarkRadiant in Visual Studio.<br />
<br />
= Install a Git Client =<br />
The main codebase is stored and maintained on github, therefore you'll need a Git client like<br />
* [http://windows.github.com/ '''Github Desktop''']<br />
* [http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git '''TortoiseGit'''] <br />
* [https://www.sourcetreeapp.com/ '''Sourcetree''']<br />
<br />
Download and install the git client into any folder of your preference. After installation it might ask to reboot your machine, as Tortoise integrates into the Explorer shell.<br />
<br />
= Download Sources and Dependencies = <br />
<br />
== Using Github Desktop ==<br />
Create your github-login, configure github desktop as desired, especially the default clone path in the options dialog. Browse to the [https://github.com/codereader/DarkRadiant github page of DarkRadiant] and click on '''Clone in Windows'''. That's it!<br />
<br />
== Using TortoiseGit ==<br />
To prepare the source download, open Windows Explorer and create the folder you want to clone (i.e. download) the sources into. Make sure the folder does not contain spaces. Use your Git client to clone the DarkRadiant repository from github:<br />
<br />
Make sure the '''recursive''' flag is checked in the dialog.<br />
<br />
[[Image:dr git clone.png|200px]]<br />
<br />
Cloning takes a minute or two - after the process is finished your folder should be looking like this:<br />
<br />
[[Image:Dr_bare_repo.png|200px]]<br />
<br />
= Compile =<br />
Start Visual Studio and open the DarkRadiant solution file (.sln) which is ready for you in the root of the repository.<br />
<br />
Select ''release'' build (unless you want to debug a problem) and hit Ctrl-Shift-B in VC++ to start building the sources or select "Build > Build Solution" from the menus.<br />
<br />
{{important|headline=Note|text=If you cloned the sources to <tt>C:\Games\DarkRadiant</tt>, the application binary will be placed in <tt>C:\Games\DarkRadiant\install\DarkRadiant.exe</tt>}}<br />
<br />
The project output files are set up in a way to automatically install the binaries in the <tt>install/</tt>, <tt>install/modules/</tt> and <tt>install/plugins/</tt> folders. Also, all dependencies from the w32deps/ folder (see previous section) are automatically copied to the install/ folder during the post-build event. If anything goes wrong during compilation, please seek help in the [http://forums.thedarkmod.com/forum/51-darkradiant-feedback-and-development/ forums].<br />
<br />
The build expects the windeps folder to be stored in the root of the source tree, it should be created automatically the first time a build is started. See below for how to set up the folders in case that step went wrong.<br />
<br />
== Manual Download of the Dependencies Package ==<br />
For Windows builds additional dependencies are automatically downloaded and copied into the source tree by the build steps in Visual Studio. If this fails for any reason, you'll have to download and extract the package yourself, either by executing the script in<br />
<br />
tools/scripts/download_windeps.ps1<br />
<br />
or by downloading the 7-zipped packages from the following URL (you can [http://www.7-zip.org get 7-zip here]):<br />
<br />
https://github.com/codereader/DarkRadiant_WinDeps/releases/latest<br />
<br />
Download and extract it directly to the directory you cloned the sources to. The resulting folder structure should look like this. <br />
<br />
[[Image:Dr_windeps_repo.png|200px]]<br />
<br />
'''Important:''' The windeps/ folder must be in the same folder as the radiant/ or include/ folder.<br />
<br />
= (Optional) Compiling the Windows Dependencies =<br />
This step is optional and more advanced. You won't need to do this if you just want to compile and run DarkRadiant using the currently maintained version of Visual Studio.<br />
<br />
Note: in the past DarkRadiant was linking against a few boost libraries requiring static libraries, this is no longer the case since August 2017.<br />
<br />
== Compile the support libraries ==<br />
DarkRadiant is using a lot of third-party libraries like libxml2, libiconv, vorbis, etc.<br />
<br />
For Windows I set up custom VC++ solutions to compile most of the libraries directly from the source (as many of those third-party projects don't offer Windows x64 binaries), these projects can be found in the <tt>winbuild</tt> folder in Git. The winbuild folder contains all the sources needed to build the x64 dependency binaries.<br />
<br />
The VC++ project files can be found in the winbuild/msvc folder. To check out the repo, go ahead like this:<br />
<br />
# Right-click your C:\Games folder >> Git Clone...<br />
# Select https://github.com/codereader/DarkRadiant_WinDeps.git to C:\Games\DarkRadiant_WinDeps<br />
<br />
or by using the git command line<br />
<br />
# git clone https://github.com/codereader/DarkRadiant_WinDeps.git C:\Games\DarkRadiant_WinDeps<br />
<br />
== Program Database Files (.pdb) ==<br />
When debugging a DarkRadiant crashdump, you'll need the program database files to get substantial information out of it, so it's vital to save the .pdb files right after compilation, otherwise they won't match against the signatures in the crashdump.<br />
<br />
As far as the windeps dependencies are concerned, I've zipped up all the .pdb files and stored them on the GitHub release page:<br />
<br />
* VC++ 2022: https://github.com/codereader/DarkRadiant_WinDeps/releases/latest (look for windeps.pdbs.7z)<br />
<br />
== See also / Links ==<br />
* [[DarkRadiant - Compilation Guide]]<br />
* [https://visualstudio.microsoft.com/downloads/ Visual Studio 2022 Community Edition]<br />
* [[Save a Memory Dump for debugging Crashes|Information about recording crash dumps]]<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compilation_Guide&diff=29451DarkRadiant - Compilation Guide2022-04-01T19:34:09Z<p>Greebo: </p>
<hr />
<div>DarkRadiant's codebase is open source, the main part of the source code is hosted on github. To compile the sources you can either use <br />
<br />
* Windows: ''Visual Studio 2022 Community Edition'' (higher editions also possible: Professional, Ultimate, ...)<br />
* Linux: gcc/g++ (Automake)<br />
* Mac OS X: Automake (after installing XCode and using MacPorts)<br />
<br />
All compilers can be acquired for free. In any case, since DarkRadiant is using part of the C++17 feature set, a compiler supporting the C++17 standard is required.<br />
<br />
= Compilation Guides =<br />
There are separate articles for Windows and Linux, select one to learn more:<br />
<br />
* [[DarkRadiant - Compiling in Windows|Compiling in Windows / Visual Studio]]<br />
* [[DarkRadiant - Compiling in Linux|Compiling in Linux]]<br />
* [[DarkRadiant - Compiling in macOS|Compiling in macOS]] (experimental)<br />
<br />
Note: The articles are always referring to the latest revision of the source code, not to a specific release.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compilation_Guide&diff=29450DarkRadiant - Compilation Guide2022-04-01T19:33:36Z<p>Greebo: </p>
<hr />
<div>DarkRadiant's codebase is open source, the main part of the source code is hosted on github. To compile the sources you can either use <br />
<br />
* Windows: ''Visual Studio 2022 Community Edition'' (higher editions also possible: Professional, Ultimate, ...)<br />
* Linux: gcc/g++ (Automake)<br />
* Mac OS X: Automake (after installing XCode and using MacPorts)<br />
<br />
All compilers can be acquired for free and should be able to produce 32 Bit and 64 Bit builds. In any case, since DarkRadiant is using part of the C++11 feature set, a compiler supporting the C++11 standard is required.<br />
<br />
= Compilation Guides =<br />
There are separate articles for Windows and Linux, select one to learn more:<br />
<br />
* [[DarkRadiant - Compiling in Windows|Compiling in Windows / Visual Studio]]<br />
* [[DarkRadiant - Compiling in Linux|Compiling in Linux]]<br />
* [[DarkRadiant - Compiling in macOS|Compiling in macOS]] (experimental)<br />
<br />
Note: The articles are always referring to the latest revision of the source code, not to a specific release.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=29312DarkRadiant Script Reference2022-03-05T03:55:57Z<p>Greebo: /* ModelPolygon */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== MeshVertex =====<br />
A MeshVertex 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).<br />
(This type has been named ArbitraryMeshVertex until 2.14.)<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three MeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>MeshVertex a</tt> The first vertex of this polygon<br />
* <tt>MeshVertex b</tt> The second vertex of this polygon<br />
* <tt>MeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=29311DarkRadiant Script Reference2022-03-05T03:55:28Z<p>Greebo: /* ArbitraryMeshVertex */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== MeshVertex =====<br />
A MeshVertex 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).<br />
(This type has been named ArbitraryMeshVertex until 2.14.)<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=29310DarkRadiant Script Reference2022-03-05T03:54:32Z<p>Greebo: /* ModelSurface */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>MeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Windows&diff=28715DarkRadiant - Compiling in Windows2021-10-12T04:56:39Z<p>Greebo: </p>
<hr />
<div>To compile the sources in Windows you will need '''Visual Studio 2019 Community Edition''' or higher. The Community Edition can be acquired for free and is able to produce 64 Bit builds. <br />
<br />
You will need a Git client to clone the sources to your machine and install the Windows dependencies package. Then you're set up to compile DarkRadiant in Visual Studio.<br />
<br />
= Install a Git Client =<br />
The main codebase is stored and maintained on github, therefore you'll need a Git client like<br />
* [http://windows.github.com/ '''Github Desktop''']<br />
* [http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git '''TortoiseGit'''] <br />
* [https://www.sourcetreeapp.com/ '''Sourcetree''']<br />
<br />
Download and install the git client into any folder of your preference. After installation it might ask to reboot your machine, as Tortoise integrates into the Explorer shell.<br />
<br />
= Download Sources and Dependencies = <br />
<br />
== Using Github Desktop ==<br />
Create your github-login, configure github desktop as desired, especially the default clone path in the options dialog. Browse to the [https://github.com/codereader/DarkRadiant github page of DarkRadiant] and click on '''Clone in Windows'''. That's it!<br />
<br />
== Using TortoiseGit ==<br />
To prepare the source download, open Windows Explorer and create the folder you want to clone (i.e. download) the sources into. Make sure the folder does not contain spaces. Use your Git client to clone the DarkRadiant repository from github:<br />
<br />
Make sure the '''recursive''' flag is checked in the dialog.<br />
<br />
[[Image:dr git clone.png|200px]]<br />
<br />
Cloning takes a minute or two - after the process is finished your folder should be looking like this:<br />
<br />
[[Image:Dr_bare_repo.png|200px]]<br />
<br />
= Compile =<br />
Start Visual Studio and open the DarkRadiant solution file (.sln) which is ready for you in the root of the repository.<br />
<br />
Select ''release'' build (unless you want to debug a problem) and hit Ctrl-Shift-B in VC++ to start building the sources or select "Build > Build Solution" from the menus.<br />
<br />
{{important|headline=Note|text=If you cloned the sources to <tt>C:\Games\DarkRadiant</tt>, the application binary will be placed in <tt>C:\Games\DarkRadiant\install\DarkRadiant.exe</tt>}}<br />
<br />
The project output files are set up in a way to automatically install the binaries in the <tt>install/</tt>, <tt>install/modules/</tt> and <tt>install/plugins/</tt> folders. Also, all dependencies from the w32deps/ folder (see previous section) are automatically copied to the install/ folder during the post-build event. If anything goes wrong during compilation, please seek help in the [http://forums.thedarkmod.com/forum/51-darkradiant-feedback-and-development/ forums].<br />
<br />
The build expects the windeps folder to be stored in the root of the source tree, it should be created automatically the first time a build is started. See below for how to set up the folders in case that step went wrong.<br />
<br />
== Manual Download of the Dependencies Package ==<br />
For Windows builds additional dependencies are automatically downloaded and copied into the source tree by the build steps in Visual Studio. If this fails for any reason, you'll have to download and extract the package yourself, either by executing the script in<br />
<br />
tools/scripts/download_windeps.ps1<br />
<br />
or by downloading the 7-zipped packages from the following URL (you can [http://www.7-zip.org get 7-zip here]):<br />
<br />
https://github.com/codereader/DarkRadiant_WinDeps/releases/latest<br />
<br />
Download and extract it directly to the directory you cloned the sources to. The resulting folder structure should look like this. <br />
<br />
[[Image:Dr_windeps_repo.png|200px]]<br />
<br />
'''Important:''' The windeps/ folder must be in the same folder as the radiant/ or include/ folder.<br />
<br />
= (Optional) Compiling the Windows Dependencies =<br />
This step is optional and more advanced. You won't need to do this if you just want to compile and run DarkRadiant using the currently maintained version of Visual Studio.<br />
<br />
Note: in the past DarkRadiant was linking against a few boost libraries requiring static libraries, this is no longer the case since August 2017.<br />
<br />
== Compile the support libraries ==<br />
DarkRadiant is using a lot of third-party libraries like libxml2, libiconv, vorbis, etc.<br />
<br />
For Windows I set up custom VC++ solutions to compile most of the libraries directly from the source (as many of those third-party projects don't offer Windows x64 binaries), these projects can be found in the <tt>winbuild</tt> folder in Git. The winbuild folder contains all the sources needed to build the x64 dependency binaries.<br />
<br />
The VC++ project files can be found in the winbuild/msvc folder. To check out the repo, go ahead like this:<br />
<br />
# Right-click your C:\Games folder >> Git Clone...<br />
# Select https://github.com/codereader/DarkRadiant_WinDeps.git to C:\Games\DarkRadiant_WinDeps<br />
<br />
or by using the git command line<br />
<br />
# git clone https://github.com/codereader/DarkRadiant_WinDeps.git C:\Games\DarkRadiant_WinDeps<br />
<br />
== Program Database Files (.pdb) ==<br />
When debugging a DarkRadiant crashdump, you'll need the program database files to get substantial information out of it, so it's vital to save the .pdb files right after compilation, otherwise they won't match against the signatures in the crashdump.<br />
<br />
As far as the windeps dependencies are concerned, I've zipped up all the .pdb files and stored them on the GitHub release page:<br />
<br />
* VC++ 2019: https://github.com/codereader/DarkRadiant_WinDeps/releases/latest (look for windeps.pdbs.7z)<br />
<br />
== See also / Links ==<br />
* [[DarkRadiant - Compilation Guide]]<br />
* [https://visualstudio.microsoft.com/downloads/ Visual Studio 2019 Community Edition]<br />
* [[Save a Memory Dump for debugging Crashes|Information about recording crash dumps]]<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Windows&diff=28714DarkRadiant - Compiling in Windows2021-10-12T04:56:01Z<p>Greebo: /* Compile the support libraries */</p>
<hr />
<div>To compile the sources in Windows you will need '''Visual Studio 2019 Community Edition''' or higher. The Community Edition can be acquired for free and is able to produce both 32 Bit and 64 Bit builds. <br />
<br />
You will need a Git client to clone the sources to your machine and install the Windows dependencies package. Then you're set up to compile DarkRadiant in Visual Studio.<br />
<br />
= Install a Git Client =<br />
The main codebase is stored and maintained on github, therefore you'll need a Git client like<br />
* [http://windows.github.com/ '''Github Desktop''']<br />
* [http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git '''TortoiseGit'''] <br />
* [https://www.sourcetreeapp.com/ '''Sourcetree''']<br />
<br />
Download and install the git client into any folder of your preference. After installation it might ask to reboot your machine, as Tortoise integrates into the Explorer shell.<br />
<br />
= Download Sources and Dependencies = <br />
<br />
== Using Github Desktop ==<br />
Create your github-login, configure github desktop as desired, especially the default clone path in the options dialog. Browse to the [https://github.com/codereader/DarkRadiant github page of DarkRadiant] and click on '''Clone in Windows'''. That's it!<br />
<br />
== Using TortoiseGit ==<br />
To prepare the source download, open Windows Explorer and create the folder you want to clone (i.e. download) the sources into. Make sure the folder does not contain spaces. Use your Git client to clone the DarkRadiant repository from github:<br />
<br />
Make sure the '''recursive''' flag is checked in the dialog.<br />
<br />
[[Image:dr git clone.png|200px]]<br />
<br />
Cloning takes a minute or two - after the process is finished your folder should be looking like this:<br />
<br />
[[Image:Dr_bare_repo.png|200px]]<br />
<br />
= Compile =<br />
Start Visual Studio and open the DarkRadiant solution file (.sln) which is ready for you in the root of the repository.<br />
<br />
Select ''release'' build (unless you want to debug a problem) and hit Ctrl-Shift-B in VC++ to start building the sources or select "Build > Build Solution" from the menus.<br />
<br />
{{important|headline=Note|text=If you cloned the sources to <tt>C:\Games\DarkRadiant</tt>, the application binary will be placed in <tt>C:\Games\DarkRadiant\install\DarkRadiant.exe</tt>}}<br />
<br />
The project output files are set up in a way to automatically install the binaries in the <tt>install/</tt>, <tt>install/modules/</tt> and <tt>install/plugins/</tt> folders. Also, all dependencies from the w32deps/ folder (see previous section) are automatically copied to the install/ folder during the post-build event. If anything goes wrong during compilation, please seek help in the [http://forums.thedarkmod.com/forum/51-darkradiant-feedback-and-development/ forums].<br />
<br />
The build expects the windeps folder to be stored in the root of the source tree, it should be created automatically the first time a build is started. See below for how to set up the folders in case that step went wrong.<br />
<br />
== Manual Download of the Dependencies Package ==<br />
For Windows builds additional dependencies are automatically downloaded and copied into the source tree by the build steps in Visual Studio. If this fails for any reason, you'll have to download and extract the package yourself, either by executing the script in<br />
<br />
tools/scripts/download_windeps.ps1<br />
<br />
or by downloading the 7-zipped packages from the following URL (you can [http://www.7-zip.org get 7-zip here]):<br />
<br />
https://github.com/codereader/DarkRadiant_WinDeps/releases/latest<br />
<br />
Download and extract it directly to the directory you cloned the sources to. The resulting folder structure should look like this. <br />
<br />
[[Image:Dr_windeps_repo.png|200px]]<br />
<br />
'''Important:''' The windeps/ folder must be in the same folder as the radiant/ or include/ folder.<br />
<br />
= (Optional) Compiling the Windows Dependencies =<br />
This step is optional and more advanced. You won't need to do this if you just want to compile and run DarkRadiant using the currently maintained version of Visual Studio.<br />
<br />
Note: in the past DarkRadiant was linking against a few boost libraries requiring static libraries, this is no longer the case since August 2017.<br />
<br />
== Compile the support libraries ==<br />
DarkRadiant is using a lot of third-party libraries like libxml2, libiconv, vorbis, etc.<br />
<br />
For Windows I set up custom VC++ solutions to compile most of the libraries directly from the source (as many of those third-party projects don't offer Windows x64 binaries), these projects can be found in the <tt>winbuild</tt> folder in Git. The winbuild folder contains all the sources needed to build the x64 dependency binaries.<br />
<br />
The VC++ project files can be found in the winbuild/msvc folder. To check out the repo, go ahead like this:<br />
<br />
# Right-click your C:\Games folder >> Git Clone...<br />
# Select https://github.com/codereader/DarkRadiant_WinDeps.git to C:\Games\DarkRadiant_WinDeps<br />
<br />
or by using the git command line<br />
<br />
# git clone https://github.com/codereader/DarkRadiant_WinDeps.git C:\Games\DarkRadiant_WinDeps<br />
<br />
== Program Database Files (.pdb) ==<br />
When debugging a DarkRadiant crashdump, you'll need the program database files to get substantial information out of it, so it's vital to save the .pdb files right after compilation, otherwise they won't match against the signatures in the crashdump.<br />
<br />
As far as the windeps dependencies are concerned, I've zipped up all the .pdb files and stored them on the GitHub release page:<br />
<br />
* VC++ 2019: https://github.com/codereader/DarkRadiant_WinDeps/releases/latest (look for windeps.pdbs.7z)<br />
<br />
== See also / Links ==<br />
* [[DarkRadiant - Compilation Guide]]<br />
* [https://visualstudio.microsoft.com/downloads/ Visual Studio 2019 Community Edition]<br />
* [[Save a Memory Dump for debugging Crashes|Information about recording crash dumps]]<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=File:Dr_git_clone.png&diff=28713File:Dr git clone.png2021-10-12T04:54:56Z<p>Greebo: Greebo uploaded a new version of File:Dr git clone.png</p>
<hr />
<div></div>Greebohttps://wiki.thedarkmod.com/index.php?title=File:Dr_windeps_repo.png&diff=28712File:Dr windeps repo.png2021-10-12T04:53:36Z<p>Greebo: Greebo uploaded a new version of File:Dr windeps repo.png</p>
<hr />
<div></div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Windows&diff=28711DarkRadiant - Compiling in Windows2021-10-12T04:50:44Z<p>Greebo: /* Compile */</p>
<hr />
<div>To compile the sources in Windows you will need '''Visual Studio 2019 Community Edition''' or higher. The Community Edition can be acquired for free and is able to produce both 32 Bit and 64 Bit builds. <br />
<br />
You will need a Git client to clone the sources to your machine and install the Windows dependencies package. Then you're set up to compile DarkRadiant in Visual Studio.<br />
<br />
= Install a Git Client =<br />
The main codebase is stored and maintained on github, therefore you'll need a Git client like<br />
* [http://windows.github.com/ '''Github Desktop''']<br />
* [http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git '''TortoiseGit'''] <br />
* [https://www.sourcetreeapp.com/ '''Sourcetree''']<br />
<br />
Download and install the git client into any folder of your preference. After installation it might ask to reboot your machine, as Tortoise integrates into the Explorer shell.<br />
<br />
= Download Sources and Dependencies = <br />
<br />
== Using Github Desktop ==<br />
Create your github-login, configure github desktop as desired, especially the default clone path in the options dialog. Browse to the [https://github.com/codereader/DarkRadiant github page of DarkRadiant] and click on '''Clone in Windows'''. That's it!<br />
<br />
== Using TortoiseGit ==<br />
To prepare the source download, open Windows Explorer and create the folder you want to clone (i.e. download) the sources into. Make sure the folder does not contain spaces. Use your Git client to clone the DarkRadiant repository from github:<br />
<br />
Make sure the '''recursive''' flag is checked in the dialog.<br />
<br />
[[Image:dr git clone.png|200px]]<br />
<br />
Cloning takes a minute or two - after the process is finished your folder should be looking like this:<br />
<br />
[[Image:Dr_bare_repo.png|200px]]<br />
<br />
= Compile =<br />
Start Visual Studio and open the DarkRadiant solution file (.sln) which is ready for you in the root of the repository.<br />
<br />
Select ''release'' build (unless you want to debug a problem) and hit Ctrl-Shift-B in VC++ to start building the sources or select "Build > Build Solution" from the menus.<br />
<br />
{{important|headline=Note|text=If you cloned the sources to <tt>C:\Games\DarkRadiant</tt>, the application binary will be placed in <tt>C:\Games\DarkRadiant\install\DarkRadiant.exe</tt>}}<br />
<br />
The project output files are set up in a way to automatically install the binaries in the <tt>install/</tt>, <tt>install/modules/</tt> and <tt>install/plugins/</tt> folders. Also, all dependencies from the w32deps/ folder (see previous section) are automatically copied to the install/ folder during the post-build event. If anything goes wrong during compilation, please seek help in the [http://forums.thedarkmod.com/forum/51-darkradiant-feedback-and-development/ forums].<br />
<br />
The build expects the windeps folder to be stored in the root of the source tree, it should be created automatically the first time a build is started. See below for how to set up the folders in case that step went wrong.<br />
<br />
== Manual Download of the Dependencies Package ==<br />
For Windows builds additional dependencies are automatically downloaded and copied into the source tree by the build steps in Visual Studio. If this fails for any reason, you'll have to download and extract the package yourself, either by executing the script in<br />
<br />
tools/scripts/download_windeps.ps1<br />
<br />
or by downloading the 7-zipped packages from the following URL (you can [http://www.7-zip.org get 7-zip here]):<br />
<br />
https://github.com/codereader/DarkRadiant_WinDeps/releases/latest<br />
<br />
Download and extract it directly to the directory you cloned the sources to. The resulting folder structure should look like this. <br />
<br />
[[Image:Dr_windeps_repo.png|200px]]<br />
<br />
'''Important:''' The windeps/ folder must be in the same folder as the radiant/ or include/ folder.<br />
<br />
= (Optional) Compiling the Windows Dependencies =<br />
This step is optional and more advanced. You won't need to do this if you just want to compile and run DarkRadiant using the currently maintained version of Visual Studio.<br />
<br />
Note: in the past DarkRadiant was linking against a few boost libraries requiring static libraries, this is no longer the case since August 2017.<br />
<br />
== Compile the support libraries ==<br />
DarkRadiant is using a lot of third-party libraries like libxml2, libiconv, vorbis, etc.<br />
<br />
For Windows I set up custom VC++ solutions to compile most of the libraries directly from the source (as many of those third-party projects don't offer Windows x64 binaries), these projects can be found in the <tt>winbuild</tt> folder in Git. The winbuild folder contains all the sources needed to build the Win32/Win64 dependency binaries. Note that the headers are stored in w32deps, as the main DarkRadiant project needs them there, so w32deps is the place to look for most of the shared headers.<br />
<br />
The VC++ project files can be found in the winbuild/msvc folder. To check out the repo, go ahead like this:<br />
<br />
# Right-click your C:\Games folder >> Git Clone...<br />
# Select https://github.com/codereader/DarkRadiant_WinDeps.git to C:\Games\DarkRadiant_WinDeps<br />
<br />
or by using the git command line<br />
<br />
# git clone https://github.com/codereader/DarkRadiant_WinDeps.git C:\Games\DarkRadiant_WinDeps<br />
<br />
== Program Database Files (.pdb) ==<br />
When debugging a DarkRadiant crashdump, you'll need the program database files to get substantial information out of it, so it's vital to save the .pdb files right after compilation, otherwise they won't match against the signatures in the crashdump.<br />
<br />
As far as the windeps dependencies are concerned, I've zipped up all the .pdb files and stored them on the GitHub release page:<br />
<br />
* VC++ 2019: https://github.com/codereader/DarkRadiant_WinDeps/releases/latest (look for windeps.pdbs.7z)<br />
<br />
== See also / Links ==<br />
* [[DarkRadiant - Compilation Guide]]<br />
* [https://visualstudio.microsoft.com/downloads/ Visual Studio 2019 Community Edition]<br />
* [[Save a Memory Dump for debugging Crashes|Information about recording crash dumps]]<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Windows&diff=28710DarkRadiant - Compiling in Windows2021-10-12T04:50:30Z<p>Greebo: /* Compile */</p>
<hr />
<div>To compile the sources in Windows you will need '''Visual Studio 2019 Community Edition''' or higher. The Community Edition can be acquired for free and is able to produce both 32 Bit and 64 Bit builds. <br />
<br />
You will need a Git client to clone the sources to your machine and install the Windows dependencies package. Then you're set up to compile DarkRadiant in Visual Studio.<br />
<br />
= Install a Git Client =<br />
The main codebase is stored and maintained on github, therefore you'll need a Git client like<br />
* [http://windows.github.com/ '''Github Desktop''']<br />
* [http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git '''TortoiseGit'''] <br />
* [https://www.sourcetreeapp.com/ '''Sourcetree''']<br />
<br />
Download and install the git client into any folder of your preference. After installation it might ask to reboot your machine, as Tortoise integrates into the Explorer shell.<br />
<br />
= Download Sources and Dependencies = <br />
<br />
== Using Github Desktop ==<br />
Create your github-login, configure github desktop as desired, especially the default clone path in the options dialog. Browse to the [https://github.com/codereader/DarkRadiant github page of DarkRadiant] and click on '''Clone in Windows'''. That's it!<br />
<br />
== Using TortoiseGit ==<br />
To prepare the source download, open Windows Explorer and create the folder you want to clone (i.e. download) the sources into. Make sure the folder does not contain spaces. Use your Git client to clone the DarkRadiant repository from github:<br />
<br />
Make sure the '''recursive''' flag is checked in the dialog.<br />
<br />
[[Image:dr git clone.png|200px]]<br />
<br />
Cloning takes a minute or two - after the process is finished your folder should be looking like this:<br />
<br />
[[Image:Dr_bare_repo.png|200px]]<br />
<br />
= Compile =<br />
Start Visual Studio and open the DarkRadiant solution file (.sln) which is ready for you in the <tt>tools/msvc</tt> folder. <br />
<br />
Select ''release'' build (unless you want to debug a problem) and hit Ctrl-Shift-B in VC++ to start building the sources or select "Build > Build Solution" from the menus.<br />
<br />
{{important|headline=Note|text=If you cloned the sources to <tt>C:\Games\DarkRadiant</tt>, the application binary will be placed in <tt>C:\Games\DarkRadiant\install\DarkRadiant.exe</tt>}}<br />
<br />
The project output files are set up in a way to automatically install the binaries in the <tt>install/</tt>, <tt>install/modules/</tt> and <tt>install/plugins/</tt> folders. Also, all dependencies from the w32deps/ folder (see previous section) are automatically copied to the install/ folder during the post-build event. If anything goes wrong during compilation, please seek help in the [http://forums.thedarkmod.com/forum/51-darkradiant-feedback-and-development/ forums].<br />
<br />
The build expects the windeps folder to be stored in the root of the source tree, it should be created automatically the first time a build is started. See below for how to set up the folders in case that step went wrong.<br />
<br />
== Manual Download of the Dependencies Package ==<br />
For Windows builds additional dependencies are automatically downloaded and copied into the source tree by the build steps in Visual Studio. If this fails for any reason, you'll have to download and extract the package yourself, either by executing the script in<br />
<br />
tools/scripts/download_windeps.ps1<br />
<br />
or by downloading the 7-zipped packages from the following URL (you can [http://www.7-zip.org get 7-zip here]):<br />
<br />
https://github.com/codereader/DarkRadiant_WinDeps/releases/latest<br />
<br />
Download and extract it directly to the directory you cloned the sources to. The resulting folder structure should look like this. <br />
<br />
[[Image:Dr_windeps_repo.png|200px]]<br />
<br />
'''Important:''' The windeps/ folder must be in the same folder as the radiant/ or include/ folder.<br />
<br />
= (Optional) Compiling the Windows Dependencies =<br />
This step is optional and more advanced. You won't need to do this if you just want to compile and run DarkRadiant using the currently maintained version of Visual Studio.<br />
<br />
Note: in the past DarkRadiant was linking against a few boost libraries requiring static libraries, this is no longer the case since August 2017.<br />
<br />
== Compile the support libraries ==<br />
DarkRadiant is using a lot of third-party libraries like libxml2, libiconv, vorbis, etc.<br />
<br />
For Windows I set up custom VC++ solutions to compile most of the libraries directly from the source (as many of those third-party projects don't offer Windows x64 binaries), these projects can be found in the <tt>winbuild</tt> folder in Git. The winbuild folder contains all the sources needed to build the Win32/Win64 dependency binaries. Note that the headers are stored in w32deps, as the main DarkRadiant project needs them there, so w32deps is the place to look for most of the shared headers.<br />
<br />
The VC++ project files can be found in the winbuild/msvc folder. To check out the repo, go ahead like this:<br />
<br />
# Right-click your C:\Games folder >> Git Clone...<br />
# Select https://github.com/codereader/DarkRadiant_WinDeps.git to C:\Games\DarkRadiant_WinDeps<br />
<br />
or by using the git command line<br />
<br />
# git clone https://github.com/codereader/DarkRadiant_WinDeps.git C:\Games\DarkRadiant_WinDeps<br />
<br />
== Program Database Files (.pdb) ==<br />
When debugging a DarkRadiant crashdump, you'll need the program database files to get substantial information out of it, so it's vital to save the .pdb files right after compilation, otherwise they won't match against the signatures in the crashdump.<br />
<br />
As far as the windeps dependencies are concerned, I've zipped up all the .pdb files and stored them on the GitHub release page:<br />
<br />
* VC++ 2019: https://github.com/codereader/DarkRadiant_WinDeps/releases/latest (look for windeps.pdbs.7z)<br />
<br />
== See also / Links ==<br />
* [[DarkRadiant - Compilation Guide]]<br />
* [https://visualstudio.microsoft.com/downloads/ Visual Studio 2019 Community Edition]<br />
* [[Save a Memory Dump for debugging Crashes|Information about recording crash dumps]]<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&diff=28605DarkRadiant - Compiling in Linux2021-08-09T17:44:34Z<p>Greebo: /* Ubuntu 20.04 and later */</p>
<hr />
<div>== Install Required Packages ==<br />
<br />
=== Ubuntu 20.04 and later ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config zlib1g-dev libjpeg-dev libxml2-dev libsigc++-2.0-dev libgtest-dev libeigen3-dev<br />
sudo apt-get install libwxgtk3.0-gtk3-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev libgit2-dev<br />
<br />
=== openSUSE Tumbleweed ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo zypper install git cmake gcc-c++ gettext-tools zlib-devel libjpeg62-devel libxml2-devel libsigc++2-devel gtest<br />
sudo zypper install wxWidgets-3_0-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python38-devel<br />
<br />
=== Mageia 8 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo urpmi git cmake make gcc-c++ libzlib-devel libjpeg-devel libwxgtku3.0-devel libsigc++2.0-devel <br />
sudo urpmi libftgl-devel libglew-devel libpython3-devel libopenal-devel libfreealut-devel libvorbis-devel lib64gtest-devel<br />
<br />
=== Debian 10 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git cmake pkg-config gettext zlib1g-dev libjpeg-dev libwxgtk3.0-dev libgtest-dev<br />
sudo apt-get install libxml2-dev libsigc++-2.0-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== Fedora 26 / 25 ===<br />
Copy and paste the following into a terminal:<br />
<br />
sudo dnf install git automake libtool gcc-c++ zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel libsigc++20-devel <br />
sudo dnf install libpng12-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python-devel pybind11-devel<br />
<br />
Note that the wxGTK package does not yet support Wayland environments, which is the default since Fedora 25 (DarkRadiant will just segfault during startup). You'll need to [https://fedoraproject.org/wiki/Changes/WaylandByDefault deactivate it] for the moment being.<br />
<br />
=== Arch Linux ===<br />
The following packages are requred after starting from an Anarchy installation using Gnome as Window Manager. <br />
<br />
sudo pacman -S cmake wxgtk2 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== CentOS 7 x64 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo yum -y install gcc gcc-c++ git automake libtool zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel <br />
sudo yum -y install libsigc++20-devel ftgl-devel glew-devel boost-devel openal-soft-devel freealut-devel libvorbis-devel python-devel<br />
<br />
CentOS 7 ships with an older compiler, so you'll need to install a more recent GCC first (following the directions on [https://stackoverflow.com/questions/36327805/how-to-install-gcc-5-3-with-yum-on-centos-7-2 stackoverflow]):<br />
<br />
sudo yum install centos-release-scl <br />
sudo yum install devtoolset-4-gcc*<br />
scl enable devtoolset-4 bash<br />
<br />
Note that the <tt>wxGTK3-devel</tt> package doesn't create a <tt>wx-config</tt> symlink in the <tt>/usr/bin</tt> directory, that's why you need to pass an additional <tt>--with-wx-config=/usr/bin/wx-config-3.0</tt> argument to the ./configure script below, like this:<br />
<br />
./configure --enable-darkmod-plugins --with-wx-config=/usr/bin/wx-config-3.0<br />
<br />
=== Slackware 14.2 ===<br />
<br />
Slackware doesn't provide precompiled packages on the one hand (unlike Debian or Arch), but already ships with a lot of libraries on the other. Stuff like git, automake, libtools and development libraries like zlib and boost are already present, but wxWidgets, openAL, ALut and FTGL need to be installed by means of a SlackBuild script. The following has been done in Slackware 14.2, so your mileage may vary.<br />
<br />
Download the Source tarballs and the SlackBuild packages from these URLs:<br />
<br />
* https://slackbuilds.org/repository/14.2/libraries/wxGTK3/<br />
* https://slackbuilds.org/repository/14.2/libraries/ftgl/<br />
* https://slackbuilds.org/repository/14.2/libraries/OpenAL/<br />
* https://slackbuilds.org/repository/14.2/libraries/freealut/<br />
<br />
Download and extract the SlackBuild <tt>.tar.gz</tt> files in your <tt>~/Downloads</tt> folder (or anywhere else where you want to have them). For instance, the wxGTK3 package can be untar'd like this:<br />
<br />
tar xzf wxGTK3.tar.gz<br />
cd wxGTK3<br />
chmod +x wxGTK3.SlackBuild<br />
<br />
Do this for all of the above libraries, that should give you the directories <tt>ftgl/</tt>, <tt>OpenAL/</tt>, <tt>wxGTK3/</tt> and <tt>freealut/</tt>. Next, download the Source Tarballs (the <tt>.tar.bz2</tt>) files from the links above and place them next to the corresponding SlackBuild script. Then run the scripts for each of them and install the build output in your system in a second step:<br />
<br />
./wxGTK3.SlackBuild<br />
<br />
This produced (on my end at least) the package <tt>/tmp/wxGTK3-3.0.2-i486-2_SBo.tgz</tt> which can be installed by the <tt>installpkg</tt> command:<br />
<br />
installpkg /tmp/wxGTK3-3.0.2-i486-2_SBo.tgz<br />
<br />
Do the same for the rest of the libraries (ftgl, OpenAL, freealut). Be aware that the freealut package depends on the OpenAL package, so you need to do the OpenAL one first. Once you have these installed, you can proceed to the build section (<tt>git clone</tt> and <tt>configure</tt> and <tt>make</tt>).<br />
<br />
=== Gentoo ===<br />
<br />
DarkRadiant can be built and installed from an unofficial ebuild repository (overlay). The easiest way to do this is with [https://packages.gentoo.org/packages/app-portage/layman app-portage/layman], which must be installed with the <tt>git</tt> use flag.<br />
<br />
In the 'overlays' section in <tt>/etc/layman/layman.cfg</tt>, add:<br />
<br />
https://raw.githubusercontent.com/varingst/varingst-overlay/master/overlay.xml<br />
<br />
Then fetch and add the overlay:<br />
<br />
# layman -f -a varingst<br />
<br />
Now that the overlay is added, you can build and install DarkRadiant with Portage:<br />
<br />
# emerge darkradiant<br />
<br />
To sync the overlay, either do it manually with layman:<br />
<br />
# layman -s varingst<br />
<br />
Or look into the [https://wiki.gentoo.org/wiki/Project:Portage/Sync various ways to hook into the portage sync system].<br />
<br />
=== Building with a non-default g++ Compiler ===<br />
DarkRadiant's codebase makes use of C++17 features, in particular std::filesystem. Not all distributions ship with a compatible g++ compiler by default, but it's possible to install a more recent compiler suite. Get the compiler package and ensure that the makefiles are called with the correct setup, e.g.<br />
CXX="g++-5.1" cmake . && make && make install<br />
<br />
=== Older Distributions / Compiling DarkRadiant 1.8 and older ===<br />
The instructions about how to compile DR 1.8 (based on GTK) in distributions published in 2012 and older have been removed. They should still be in the [http://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&oldid=18927 history] of this page, should they ever be needed.<br />
<br />
== Obtain the source ==<br />
<br />
Make sure you have the git client installed, this is covered in the package installation commands above. <br />
Next, change to the directory where you want the source code to be in and then clone the Git repository with:<br />
<br />
git clone git://github.com/codereader/DarkRadiant.git --recurse-submodules<br />
<br />
Once the initial clone is done, the source can be updated to the latest version from inside the working directory with:<br />
<br />
git pull<br />
<br />
== Configure and Compile ==<br />
DarkRadiant employs the CMake build system under Linux as used in many open-source projects. Make sure you have the CMake toolchain downloaded, this is covered in the package installation commands above.<br />
<br />
To build DarkRadiant, run the typical chain of CMake and make commands:<br />
<br />
cmake .<br />
make<br />
[sudo] make install<br />
<br />
By the above, a release build will be created; if a debug build is required pass the <tt>-DCMAKE_BUILD_TYPE=Debug</tt> option to the cmake command script.<br />
<br />
Other points to note about the configure process:<br />
<br />
* The DarkMod-specific plugins are built by default, the <tt>-DENABLE_DM_PLUGINS=OFF</tt> argument will disable them.<br />
* The CMake script autodetects required dependencies, and will conditionally enable optional components of DarkRadiant (such as the sound plugin) based on what it finds.<br />
* For quick testing of a DarkRadiant build, it is desirable to install it into a temporary location rather than the default of <tt>/usr/local</tt>; for this, simply pass a prefix option such as <tt>-DCMAKE_INSTALL_PREFIX=/tmp/dr</tt> to cmake, after which DarkRadiant will be installed in <tt>/tmp/dr/bin/darkradiant</tt>.<br />
<br />
=== Multiprocessor Systems ===<br />
<br />
You can pass the <tt>--jobs=N</tt> parameter to make:<br />
make --jobs=2<br />
to use more than one processor for the compilation. This will eat lots of RAM, so don't do this on machines with little available memory.<br />
<br />
=== Building a .deb package ===<br />
<br />
To build a Debian/Ubuntu package, simply run<br />
<br />
dpkg-buildpackage -rfakeroot<br />
<br />
in the main <tt>darkradiant</tt> directory. The .deb will be created in the parent directory.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28571DarkRadiant Script Reference2021-06-09T18:16:01Z<p>Greebo: /* GlobalLayerManager */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalLayerManager ===<br />
The GlobalLayerManager instance provides methods for organising and manipulating layers. (since 2.10.0).<br />
* <tt>int createLayer(string name)</tt> Creates a new layer with the given name, returns the ID.<br />
* <tt>deleteLayer(int id)</tt> Deletes the layer with the given ID.<br />
* <tt>foreachLayer(LayerVisitor visitor)</tt> Calls the given visitor object with the id and name of each layer.<br />
* <tt>int getLayerID(string name)</tt> Looks up the ID for the given named layer, returns -1 if the layer doesn't exist.<br />
* <tt>string getLayerName(int id)</tt> Looks up the name for the given layer ID, returns an empty string if the layer doesn't exist.<br />
* <tt>bool layerExists(int id)</tt> Returns true if the layer with the given ID exists, false otherwise.<br />
* <tt>bool renameLayer(int id, string newName)</tt> Renames the layer with the given ID, returns true on success.<br />
* <tt>int getFirstVisibleLayer()</tt> Returns the ID of the first visible layer.<br />
* <tt>int getActiveLayer()</tt> Returns the ID of the active layer.<br />
* <tt>setActiveLayer(int id)</tt> Makes the layer with the given ID the active layer.<br />
* <tt>bool layerIsVisible(int id)</tt> Returns true if the layer with the given ID is visible, false otherwise.<br />
* <tt>bool layerIsVisible(string name)</tt> Returns true if the layer with the given name is visible, false otherwise.<br />
* <tt>setLayerVisibility(string name, bool visible)</tt> Makes the layer with the given name visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>setLayerVisibility(int id, bool visible)</tt> Makes the layer with the given ID visible or invisible, depending on the value of the "visible" flag.<br />
* <tt>addSelectionToLayer(int id)</tt> Adds the current map selection to the layer with the given ID.<br />
* <tt>addSelectionToLayer(string name)</tt> Adds the current map selection to the layer with the given name.<br />
* <tt>moveSelectionToLayer(int id)</tt> Moves the current map selection to the layer with the given ID.<br />
* <tt>moveSelectionToLayer(string name)</tt> Moves the current map selection to the layer with the given name.<br />
* <tt>removeSelectionFromLayer(int id)</tt> Removes the current map selection from the layer with the given ID.<br />
* <tt>removeSelectionFromLayer(string name)</tt> Removes the current map selection from the layer with the given name.<br />
* <tt>setSelected(int id, bool selected)</tt> Selects or deselects all members of the layer with the given ID.<br />
<br />
==== LayerVisitor ====<br />
Create an object deriving from this LayerVisitor and use it to visit every layer in the loaded map.<br />
* <tt>visit(int layerId, string layerName)</tt> Required method which is called for every layer when using <tt>GlobalLayerManager.foreachLayer()</tt><br />
'''Example'''<br />
import darkradiant as dr<br />
<br />
class LayerPrinter(dr.LayerVisitor):<br />
def visit(self, layerID, layerName):<br />
print(layerID, layerName)<br />
layerPrinter = LayerPrinter()<br />
GlobalLayerManager.foreachLayer(layerPrinter)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28570DarkRadiant Script Reference2021-06-09T17:55:39Z<p>Greebo: /* GlobalSelectionSystem */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== Visiting Faces ====<br />
The following snippet calls the <tt>visitFace</tt> method for every selected face in the scene:<br />
# Visit every selected face<br />
import darkradiant as dr<br />
<br />
class FaceVisitor(dr.SelectedFaceVisitor) :<br />
def visitFace(self, face):<br />
print(face.getShader())<br />
<br />
visitor = FaceVisitor()<br />
GlobalSelectionSystem.foreachSelectedFace(visitor)<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28569DarkRadiant Script Reference2021-06-09T17:47:33Z<p>Greebo: /* GlobalSelectionSystem */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>foreachSelectedFace(SelectedFaceVisitor visitor)</tt> Visits all selected faces using the given FaceVisitor object (since 2.13.0).<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28568DarkRadiant Script Reference2021-06-09T17:46:37Z<p>Greebo: /* GlobalCameraManager */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
* <tt>refresh()</tt> Requests a repaint of the camera view (since 2.13.0)<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&diff=28565DarkRadiant - Compiling in Linux2021-06-08T18:04:52Z<p>Greebo: /* Arch Linux */</p>
<hr />
<div>== Install Required Packages ==<br />
<br />
=== Ubuntu 20.04 and later ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config zlib1g-dev libjpeg-dev libxml2-dev libsigc++-2.0-dev libgtest-dev libeigen3-dev<br />
sudo apt-get install libwxgtk3.0-gtk3-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== openSUSE Tumbleweed ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo zypper install git cmake gcc-c++ gettext-tools zlib-devel libjpeg62-devel libxml2-devel libsigc++2-devel gtest<br />
sudo zypper install wxWidgets-3_0-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python38-devel<br />
<br />
=== Mageia 8 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo urpmi git cmake make gcc-c++ libzlib-devel libjpeg-devel libwxgtku3.0-devel libsigc++2.0-devel <br />
sudo urpmi libftgl-devel libglew-devel libpython3-devel libopenal-devel libfreealut-devel libvorbis-devel lib64gtest-devel<br />
<br />
=== Debian 10 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git cmake pkg-config gettext zlib1g-dev libjpeg-dev libwxgtk3.0-dev libgtest-dev<br />
sudo apt-get install libxml2-dev libsigc++-2.0-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== Fedora 26 / 25 ===<br />
Copy and paste the following into a terminal:<br />
<br />
sudo dnf install git automake libtool gcc-c++ zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel libsigc++20-devel <br />
sudo dnf install libpng12-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python-devel pybind11-devel<br />
<br />
Note that the wxGTK package does not yet support Wayland environments, which is the default since Fedora 25 (DarkRadiant will just segfault during startup). You'll need to [https://fedoraproject.org/wiki/Changes/WaylandByDefault deactivate it] for the moment being.<br />
<br />
=== Arch Linux ===<br />
The following packages are requred after starting from an Anarchy installation using Gnome as Window Manager. <br />
<br />
sudo pacman -S cmake wxgtk2 ftgl glew freealut libvorbis python libsigc++ eigen<br />
<br />
=== CentOS 7 x64 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo yum -y install gcc gcc-c++ git automake libtool zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel <br />
sudo yum -y install libsigc++20-devel ftgl-devel glew-devel boost-devel openal-soft-devel freealut-devel libvorbis-devel python-devel<br />
<br />
CentOS 7 ships with an older compiler, so you'll need to install a more recent GCC first (following the directions on [https://stackoverflow.com/questions/36327805/how-to-install-gcc-5-3-with-yum-on-centos-7-2 stackoverflow]):<br />
<br />
sudo yum install centos-release-scl <br />
sudo yum install devtoolset-4-gcc*<br />
scl enable devtoolset-4 bash<br />
<br />
Note that the <tt>wxGTK3-devel</tt> package doesn't create a <tt>wx-config</tt> symlink in the <tt>/usr/bin</tt> directory, that's why you need to pass an additional <tt>--with-wx-config=/usr/bin/wx-config-3.0</tt> argument to the ./configure script below, like this:<br />
<br />
./configure --enable-darkmod-plugins --with-wx-config=/usr/bin/wx-config-3.0<br />
<br />
=== Slackware 14.2 ===<br />
<br />
Slackware doesn't provide precompiled packages on the one hand (unlike Debian or Arch), but already ships with a lot of libraries on the other. Stuff like git, automake, libtools and development libraries like zlib and boost are already present, but wxWidgets, openAL, ALut and FTGL need to be installed by means of a SlackBuild script. The following has been done in Slackware 14.2, so your mileage may vary.<br />
<br />
Download the Source tarballs and the SlackBuild packages from these URLs:<br />
<br />
* https://slackbuilds.org/repository/14.2/libraries/wxGTK3/<br />
* https://slackbuilds.org/repository/14.2/libraries/ftgl/<br />
* https://slackbuilds.org/repository/14.2/libraries/OpenAL/<br />
* https://slackbuilds.org/repository/14.2/libraries/freealut/<br />
<br />
Download and extract the SlackBuild <tt>.tar.gz</tt> files in your <tt>~/Downloads</tt> folder (or anywhere else where you want to have them). For instance, the wxGTK3 package can be untar'd like this:<br />
<br />
tar xzf wxGTK3.tar.gz<br />
cd wxGTK3<br />
chmod +x wxGTK3.SlackBuild<br />
<br />
Do this for all of the above libraries, that should give you the directories <tt>ftgl/</tt>, <tt>OpenAL/</tt>, <tt>wxGTK3/</tt> and <tt>freealut/</tt>. Next, download the Source Tarballs (the <tt>.tar.bz2</tt>) files from the links above and place them next to the corresponding SlackBuild script. Then run the scripts for each of them and install the build output in your system in a second step:<br />
<br />
./wxGTK3.SlackBuild<br />
<br />
This produced (on my end at least) the package <tt>/tmp/wxGTK3-3.0.2-i486-2_SBo.tgz</tt> which can be installed by the <tt>installpkg</tt> command:<br />
<br />
installpkg /tmp/wxGTK3-3.0.2-i486-2_SBo.tgz<br />
<br />
Do the same for the rest of the libraries (ftgl, OpenAL, freealut). Be aware that the freealut package depends on the OpenAL package, so you need to do the OpenAL one first. Once you have these installed, you can proceed to the build section (<tt>git clone</tt> and <tt>configure</tt> and <tt>make</tt>).<br />
<br />
=== Gentoo ===<br />
<br />
DarkRadiant can be built and installed from an unofficial ebuild repository (overlay). The easiest way to do this is with [https://packages.gentoo.org/packages/app-portage/layman app-portage/layman], which must be installed with the <tt>git</tt> use flag.<br />
<br />
In the 'overlays' section in <tt>/etc/layman/layman.cfg</tt>, add:<br />
<br />
https://raw.githubusercontent.com/varingst/varingst-overlay/master/overlay.xml<br />
<br />
Then fetch and add the overlay:<br />
<br />
# layman -f -a varingst<br />
<br />
Now that the overlay is added, you can build and install DarkRadiant with Portage:<br />
<br />
# emerge darkradiant<br />
<br />
To sync the overlay, either do it manually with layman:<br />
<br />
# layman -s varingst<br />
<br />
Or look into the [https://wiki.gentoo.org/wiki/Project:Portage/Sync various ways to hook into the portage sync system].<br />
<br />
=== Building with a non-default g++ Compiler ===<br />
DarkRadiant's codebase makes use of C++17 features, in particular std::filesystem. Not all distributions ship with a compatible g++ compiler by default, but it's possible to install a more recent compiler suite. Get the compiler package and ensure that the makefiles are called with the correct setup, e.g.<br />
CXX="g++-5.1" cmake . && make && make install<br />
<br />
=== Older Distributions / Compiling DarkRadiant 1.8 and older ===<br />
The instructions about how to compile DR 1.8 (based on GTK) in distributions published in 2012 and older have been removed. They should still be in the [http://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&oldid=18927 history] of this page, should they ever be needed.<br />
<br />
== Obtain the source ==<br />
<br />
Make sure you have the git client installed, this is covered in the package installation commands above. <br />
Next, change to the directory where you want the source code to be in and then clone the Git repository with:<br />
<br />
git clone git://github.com/codereader/DarkRadiant.git --recurse-submodules<br />
<br />
Once the initial clone is done, the source can be updated to the latest version from inside the working directory with:<br />
<br />
git pull<br />
<br />
== Configure and Compile ==<br />
DarkRadiant employs the CMake build system under Linux as used in many open-source projects. Make sure you have the CMake toolchain downloaded, this is covered in the package installation commands above.<br />
<br />
To build DarkRadiant, run the typical chain of CMake and make commands:<br />
<br />
cmake .<br />
make<br />
[sudo] make install<br />
<br />
By the above, a release build will be created; if a debug build is required pass the <tt>-DCMAKE_BUILD_TYPE=Debug</tt> option to the cmake command script.<br />
<br />
Other points to note about the configure process:<br />
<br />
* The DarkMod-specific plugins are built by default, the <tt>-DENABLE_DM_PLUGINS=OFF</tt> argument will disable them.<br />
* The CMake script autodetects required dependencies, and will conditionally enable optional components of DarkRadiant (such as the sound plugin) based on what it finds.<br />
* For quick testing of a DarkRadiant build, it is desirable to install it into a temporary location rather than the default of <tt>/usr/local</tt>; for this, simply pass a prefix option such as <tt>-DCMAKE_INSTALL_PREFIX=/tmp/dr</tt> to cmake, after which DarkRadiant will be installed in <tt>/tmp/dr/bin/darkradiant</tt>.<br />
<br />
=== Multiprocessor Systems ===<br />
<br />
You can pass the <tt>--jobs=N</tt> parameter to make:<br />
make --jobs=2<br />
to use more than one processor for the compilation. This will eat lots of RAM, so don't do this on machines with little available memory.<br />
<br />
=== Building a .deb package ===<br />
<br />
To build a Debian/Ubuntu package, simply run<br />
<br />
dpkg-buildpackage -rfakeroot<br />
<br />
in the main <tt>darkradiant</tt> directory. The .deb will be created in the parent directory.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28559DarkRadiant Script Reference2021-06-06T04:23:25Z<p>Greebo: /* SceneNode */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "patch", "brush", "model", "particle", "entityconnection", "mergeaction", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28558DarkRadiant Script Reference2021-06-06T04:19:59Z<p>Greebo: /* GlobalMap */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "primitive", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>SceneNode getRoot()</tt> Returns the root node of the currently loaded map. This can be a NULL node if no map is active. (since 2.13.0)<br />
* <tt>bool isModified()</tt> Returns true (1) if the current map has been modified. (since 2.13.0)<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
* <tt>MapEditMode getEditMode()</tt> Returns the current edit mode. This is either <tt>MapEditMode.Normal</tt> or <tt>MapEditMode.Merge</tt> (since 2.13.0)<br />
* <tt>setEditMode(MapEditMode mode)</tt> Sets the current edit mode. (since 2.13.0)<br />
* <tt>StringList getPointFileList()</tt> Gets the list of available point files for the current map. (since 2.13.0)<br />
* <tt>showPointFile(string path)</tt> Loads and displays the given point file. (since 2.13.0)<br />
* <tt>isPointTraceVisible()</tt> Returns true (1) if there's a point file visualisation active. (since 2.13.0)<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&diff=28300DarkRadiant - Compiling in Linux2021-04-14T02:52:56Z<p>Greebo: /* Ubuntu 20.04 and later */</p>
<hr />
<div>== Install Required Packages ==<br />
<br />
=== Ubuntu 20.04 and later ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config zlib1g-dev libjpeg-dev libxml2-dev libsigc++-2.0-dev libgtest-dev libeigen3-dev<br />
sudo apt-get install libwxgtk3.0-gtk3-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== openSUSE Tumbleweed ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo zypper install git cmake gcc-c++ gettext-tools zlib-devel libjpeg62-devel libxml2-devel libsigc++2-devel gtest<br />
sudo zypper install wxWidgets-3_0-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python38-devel<br />
<br />
=== Mageia 8 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo urpmi git cmake make gcc-c++ libzlib-devel libjpeg-devel libwxgtku3.0-devel libsigc++2.0-devel <br />
sudo urpmi libftgl-devel libglew-devel libpython3-devel libopenal-devel libfreealut-devel libvorbis-devel lib64gtest-devel<br />
<br />
=== Debian 10 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git cmake pkg-config gettext zlib1g-dev libjpeg-dev libwxgtk3.0-dev libgtest-dev<br />
sudo apt-get install libxml2-dev libsigc++-2.0-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== Fedora 26 / 25 ===<br />
Copy and paste the following into a terminal:<br />
<br />
sudo dnf install git automake libtool gcc-c++ zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel libsigc++20-devel <br />
sudo dnf install libpng12-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python-devel pybind11-devel<br />
<br />
Note that the wxGTK package does not yet support Wayland environments, which is the default since Fedora 25 (DarkRadiant will just segfault during startup). You'll need to [https://fedoraproject.org/wiki/Changes/WaylandByDefault deactivate it] for the moment being.<br />
<br />
=== Arch Linux ===<br />
The following packages are requred after starting from an Anarchy installation using Gnome as Window Manager. <br />
<br />
sudo pacman -S cmake wxgtk ftgl glew freealut<br />
<br />
=== CentOS 7 x64 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo yum -y install gcc gcc-c++ git automake libtool zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel <br />
sudo yum -y install libsigc++20-devel ftgl-devel glew-devel boost-devel openal-soft-devel freealut-devel libvorbis-devel python-devel<br />
<br />
CentOS 7 ships with an older compiler, so you'll need to install a more recent GCC first (following the directions on [https://stackoverflow.com/questions/36327805/how-to-install-gcc-5-3-with-yum-on-centos-7-2 stackoverflow]):<br />
<br />
sudo yum install centos-release-scl <br />
sudo yum install devtoolset-4-gcc*<br />
scl enable devtoolset-4 bash<br />
<br />
Note that the <tt>wxGTK3-devel</tt> package doesn't create a <tt>wx-config</tt> symlink in the <tt>/usr/bin</tt> directory, that's why you need to pass an additional <tt>--with-wx-config=/usr/bin/wx-config-3.0</tt> argument to the ./configure script below, like this:<br />
<br />
./configure --enable-darkmod-plugins --with-wx-config=/usr/bin/wx-config-3.0<br />
<br />
=== Slackware 14.2 ===<br />
<br />
Slackware doesn't provide precompiled packages on the one hand (unlike Debian or Arch), but already ships with a lot of libraries on the other. Stuff like git, automake, libtools and development libraries like zlib and boost are already present, but wxWidgets, openAL, ALut and FTGL need to be installed by means of a SlackBuild script. The following has been done in Slackware 14.2, so your mileage may vary.<br />
<br />
Download the Source tarballs and the SlackBuild packages from these URLs:<br />
<br />
* https://slackbuilds.org/repository/14.2/libraries/wxGTK3/<br />
* https://slackbuilds.org/repository/14.2/libraries/ftgl/<br />
* https://slackbuilds.org/repository/14.2/libraries/OpenAL/<br />
* https://slackbuilds.org/repository/14.2/libraries/freealut/<br />
<br />
Download and extract the SlackBuild <tt>.tar.gz</tt> files in your <tt>~/Downloads</tt> folder (or anywhere else where you want to have them). For instance, the wxGTK3 package can be untar'd like this:<br />
<br />
tar xzf wxGTK3.tar.gz<br />
cd wxGTK3<br />
chmod +x wxGTK3.SlackBuild<br />
<br />
Do this for all of the above libraries, that should give you the directories <tt>ftgl/</tt>, <tt>OpenAL/</tt>, <tt>wxGTK3/</tt> and <tt>freealut/</tt>. Next, download the Source Tarballs (the <tt>.tar.bz2</tt>) files from the links above and place them next to the corresponding SlackBuild script. Then run the scripts for each of them and install the build output in your system in a second step:<br />
<br />
./wxGTK3.SlackBuild<br />
<br />
This produced (on my end at least) the package <tt>/tmp/wxGTK3-3.0.2-i486-2_SBo.tgz</tt> which can be installed by the <tt>installpkg</tt> command:<br />
<br />
installpkg /tmp/wxGTK3-3.0.2-i486-2_SBo.tgz<br />
<br />
Do the same for the rest of the libraries (ftgl, OpenAL, freealut). Be aware that the freealut package depends on the OpenAL package, so you need to do the OpenAL one first. Once you have these installed, you can proceed to the build section (<tt>git clone</tt> and <tt>configure</tt> and <tt>make</tt>).<br />
<br />
=== Gentoo ===<br />
<br />
DarkRadiant can be built and installed from an unofficial ebuild repository (overlay). The easiest way to do this is with [https://packages.gentoo.org/packages/app-portage/layman app-portage/layman], which must be installed with the <tt>git</tt> use flag.<br />
<br />
In the 'overlays' section in <tt>/etc/layman/layman.cfg</tt>, add:<br />
<br />
https://raw.githubusercontent.com/varingst/varingst-overlay/master/overlay.xml<br />
<br />
Then fetch and add the overlay:<br />
<br />
# layman -f -a varingst<br />
<br />
Now that the overlay is added, you can build and install DarkRadiant with Portage:<br />
<br />
# emerge darkradiant<br />
<br />
To sync the overlay, either do it manually with layman:<br />
<br />
# layman -s varingst<br />
<br />
Or look into the [https://wiki.gentoo.org/wiki/Project:Portage/Sync various ways to hook into the portage sync system].<br />
<br />
=== Building with a non-default g++ Compiler ===<br />
DarkRadiant's codebase makes use of C++17 features, in particular std::filesystem. Not all distributions ship with a compatible g++ compiler by default, but it's possible to install a more recent compiler suite. Get the compiler package and ensure that the makefiles are called with the correct setup, e.g.<br />
CXX="g++-5.1" cmake . && make && make install<br />
<br />
=== Older Distributions / Compiling DarkRadiant 1.8 and older ===<br />
The instructions about how to compile DR 1.8 (based on GTK) in distributions published in 2012 and older have been removed. They should still be in the [http://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&oldid=18927 history] of this page, should they ever be needed.<br />
<br />
== Obtain the source ==<br />
<br />
Make sure you have the git client installed, this is covered in the package installation commands above. <br />
Next, change to the directory where you want the source code to be in and then clone the Git repository with:<br />
<br />
git clone git://github.com/codereader/DarkRadiant.git --recurse-submodules<br />
<br />
Once the initial clone is done, the source can be updated to the latest version from inside the working directory with:<br />
<br />
git pull<br />
<br />
== Configure and Compile ==<br />
DarkRadiant employs the CMake build system under Linux as used in many open-source projects. Make sure you have the CMake toolchain downloaded, this is covered in the package installation commands above.<br />
<br />
To build DarkRadiant, run the typical chain of CMake and make commands:<br />
<br />
cmake .<br />
make<br />
[sudo] make install<br />
<br />
By the above, a release build will be created; if a debug build is required pass the <tt>-DCMAKE_BUILD_TYPE=Debug</tt> option to the cmake command script.<br />
<br />
Other points to note about the configure process:<br />
<br />
* The DarkMod-specific plugins are built by default, the <tt>-DENABLE_DM_PLUGINS=OFF</tt> argument will disable them.<br />
* The CMake script autodetects required dependencies, and will conditionally enable optional components of DarkRadiant (such as the sound plugin) based on what it finds.<br />
* For quick testing of a DarkRadiant build, it is desirable to install it into a temporary location rather than the default of <tt>/usr/local</tt>; for this, simply pass a prefix option such as <tt>-DCMAKE_INSTALL_PREFIX=/tmp/dr</tt> to cmake, after which DarkRadiant will be installed in <tt>/tmp/dr/bin/darkradiant</tt>.<br />
<br />
=== Multiprocessor Systems ===<br />
<br />
You can pass the <tt>--jobs=N</tt> parameter to make:<br />
make --jobs=2<br />
to use more than one processor for the compilation. This will eat lots of RAM, so don't do this on machines with little available memory.<br />
<br />
=== Building a .deb package ===<br />
<br />
To build a Debian/Ubuntu package, simply run<br />
<br />
dpkg-buildpackage -rfakeroot<br />
<br />
in the main <tt>darkradiant</tt> directory. The .deb will be created in the parent directory.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Windows&diff=28282DarkRadiant - Compiling in Windows2021-04-13T03:02:21Z<p>Greebo: /* Compile */</p>
<hr />
<div>To compile the sources in Windows you will need '''Visual Studio 2019 Community Edition''' or higher. The Community Edition can be acquired for free and is able to produce both 32 Bit and 64 Bit builds. <br />
<br />
You will need a Git client to clone the sources to your machine and install the Windows dependencies package. Then you're set up to compile DarkRadiant in Visual Studio.<br />
<br />
= Install a Git Client =<br />
The main codebase is stored and maintained on github, therefore you'll need a Git client like<br />
* [http://windows.github.com/ '''Github Desktop''']<br />
* [http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git '''TortoiseGit'''] <br />
<br />
Download and install the git client into any folder of your preference. After installation it might ask to reboot your machine, as Tortoise integrates into the Explorer shell.<br />
<br />
= Download Sources and Dependencies = <br />
<br />
== Using Github Desktop ==<br />
Create your github-login, configure github desktop as desired, especially the default clone path in the options dialog. Browse to the [https://github.com/codereader/DarkRadiant github page of DarkRadiant] and click on '''Clone in Windows'''. That's it!<br />
<br />
== Using TortoiseGit ==<br />
To prepare the source download, open Windows Explorer and create the folder you want to clone (i.e. download) the sources into. Make sure the folder does not contain spaces. Use your Git client to clone the DarkRadiant repository from github:<br />
<br />
Make sure the '''recursive''' flag is checked in the dialog.<br />
<br />
[[Image:dr git clone.png|200px]]<br />
<br />
Cloning takes a minute or two - after the process is finished your folder should be looking like this:<br />
<br />
[[Image:Dr_bare_repo.png|200px]]<br />
<br />
= Compile =<br />
Start Visual Studio and open the DarkRadiant solution file (.sln) which is ready for you in the <tt>tools/msvc</tt> folder. <br />
<br />
To build a package for the x64 target, make sure to select the ''x64'' platform from the configuration manager's dropdown box (located in Visual Studio's toolbar). If you prefer a 32 bit build, select the Win32 target. <br />
<br />
Select ''release'' build (unless you want to debug a problem) and hit Ctrl-Shift-B in VC++ to start building the sources or select "Build > Build Solution" from the menus.<br />
<br />
{{important|headline=Note|text=If you cloned the sources to <tt>C:\Games\DarkRadiant</tt>, the application binary will be placed in <tt>C:\Games\DarkRadiant\install\DarkRadiant.exe</tt>}}<br />
<br />
The project output files are set up in a way to automatically install the binaries in the <tt>install/</tt>, <tt>install/modules/</tt> and <tt>install/plugins/</tt> folders. Also, all dependencies from the w32deps/ folder (see previous section) are automatically copied to the install/ folder during the post-build event. If anything goes wrong during compilation, please seek help in the [http://forums.thedarkmod.com/forum/51-darkradiant-feedback-and-development/ forums].<br />
<br />
The build expects the w32deps folder to be located alongside the sources, especially x64 builds expect the w64deps folder to be sitting next to it. This should happen automatically the first time a build is started. See below for how to set up the folders in case that step went wrong.<br />
<br />
== Manual Download of the Dependencies Package ==<br />
For Windows builds additional dependencies are automatically downloaded and copied into the source tree by the build steps in Visual Studio. If this fails for any reason, you'll have to download and extract the package yourself, either by executing the script in<br />
<br />
tools/scripts/download_windeps.ps1<br />
<br />
or by downloading the 7-zipped packages from the following URL (you can [http://www.7-zip.org get 7-zip here]):<br />
<br />
https://github.com/codereader/DarkRadiant_WinDeps/releases/latest<br />
<br />
Download and extract it directly to the directory you cloned the sources to. The resulting folder structure should look like this. <br />
<br />
[[Image:Dr_windeps_repo.png|200px]]<br />
<br />
'''Important:''' The w32deps/ and w64deps/ folder must be in the same folder as the radiant/ or include/ folder.<br />
<br />
= (Optional) Compiling the Windows Dependencies =<br />
This step is optional and more advanced. You won't need to do this if you just want to compile and run DarkRadiant using the currently maintained version of Visual Studio.<br />
<br />
Note: in the past DarkRadiant was linking against a few boost libraries requiring static libraries, this is no longer the case since August 2017.<br />
<br />
== Compile the support libraries ==<br />
DarkRadiant is using a lot of third-party libraries like libxml2, libiconv, vorbis, etc.<br />
<br />
For Windows I set up custom VC++ solutions to compile most of the libraries directly from the source (as many of those third-party projects don't offer Windows x64 binaries), these projects can be found in the <tt>winbuild</tt> folder in Git. The winbuild folder contains all the sources needed to build the Win32/Win64 dependency binaries. Note that the headers are stored in w32deps, as the main DarkRadiant project needs them there, so w32deps is the place to look for most of the shared headers.<br />
<br />
The VC++ project files can be found in the winbuild/msvc folder. To check out the repo, go ahead like this:<br />
<br />
# Right-click your C:\Games folder >> Git Clone...<br />
# Select https://github.com/codereader/DarkRadiant_WinDeps.git to C:\Games\DarkRadiant_WinDeps<br />
<br />
or by using the git command line<br />
<br />
# git clone https://github.com/codereader/DarkRadiant_WinDeps.git C:\Games\DarkRadiant_WinDeps<br />
<br />
== Program Database Files (.pdb) ==<br />
When debugging a DarkRadiant crashdump, you'll need the program database files to get substantial information out of it, so it's vital to save the .pdb files right after compilation, otherwise they won't match against the signatures in the crashdump.<br />
<br />
As far as the windeps dependencies are concerned, I've zipped up all the .pdb files and stored them on the GitHub release page:<br />
<br />
* VC++ 2019: https://github.com/codereader/DarkRadiant_WinDeps/releases/latest (look for windeps.pdbs.7z)<br />
<br />
== See also / Links ==<br />
* [[DarkRadiant - Compilation Guide]]<br />
* [https://visualstudio.microsoft.com/downloads/ Visual Studio 2019 Community Edition]<br />
* [[Save a Memory Dump for debugging Crashes|Information about recording crash dumps]]<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Windows&diff=28279DarkRadiant - Compiling in Windows2021-04-12T18:01:22Z<p>Greebo: /* Program Database Files (.pdb) */</p>
<hr />
<div>To compile the sources in Windows you will need '''Visual Studio 2019 Community Edition''' or higher. The Community Edition can be acquired for free and is able to produce both 32 Bit and 64 Bit builds. <br />
<br />
You will need a Git client to clone the sources to your machine and install the Windows dependencies package. Then you're set up to compile DarkRadiant in Visual Studio.<br />
<br />
= Install a Git Client =<br />
The main codebase is stored and maintained on github, therefore you'll need a Git client like<br />
* [http://windows.github.com/ '''Github Desktop''']<br />
* [http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git '''TortoiseGit'''] <br />
<br />
Download and install the git client into any folder of your preference. After installation it might ask to reboot your machine, as Tortoise integrates into the Explorer shell.<br />
<br />
= Download Sources and Dependencies = <br />
<br />
== Using Github Desktop ==<br />
Create your github-login, configure github desktop as desired, especially the default clone path in the options dialog. Browse to the [https://github.com/codereader/DarkRadiant github page of DarkRadiant] and click on '''Clone in Windows'''. That's it!<br />
<br />
== Using TortoiseGit ==<br />
To prepare the source download, open Windows Explorer and create the folder you want to clone (i.e. download) the sources into. Make sure the folder does not contain spaces. Use your Git client to clone the DarkRadiant repository from github:<br />
<br />
Make sure the '''recursive''' flag is checked in the dialog.<br />
<br />
[[Image:dr git clone.png|200px]]<br />
<br />
Cloning takes a minute or two - after the process is finished your folder should be looking like this:<br />
<br />
[[Image:Dr_bare_repo.png|200px]]<br />
<br />
= Compile =<br />
Start Visual Studio and open the DarkRadiant solution file (.sln) which is ready for you in the <tt>tools/msvc</tt> folder. <br />
<br />
To build a package for the x64 target, make sure to select the ''x64'' platform from the configuration manager's dropdown box (located in Visual Studio's toolbar). If you prefer a 32 bit build, select the Win32 target. <br />
<br />
Select ''release'' build (unless you want to debug a problem) and hit Ctrl-Shift-B in VC++ to start building the sources or select "Build > Build Solution" from the menus.<br />
<br />
{{important|headline=Note|text=If you cloned the sources to <tt>C:\Games\DarkRadiant</tt>, the application binary will be placed in <tt>C:\Games\DarkRadiant\install\DarkRadiant.exe</tt>}}<br />
<br />
The project output files are set up in a way to automatically install the binaries in the <tt>install/</tt>, <tt>install/modules/</tt> and <tt>install/plugins/</tt> folders. Also, all dependencies from the w32deps/ folder (see previous section) are automatically copied to the install/ folder during the post-build event. If anything goes wrong during compilation, please seek help in the [http://forums.thedarkmod.com/forum/51-darkradiant-feedback-and-development/ forums].<br />
<br />
The build expects the w32deps folder to be located alongside the sources, especially x64 builds expect the w64deps folder to be sitting next to it. See above for how to set up the folders in case you missed that step. For both platforms the output will be placed in the same install/ directory.<br />
<br />
== Manual Download of the Dependencies Package ==<br />
For Windows builds additional dependencies are automatically downloaded and copied into the source tree by the build steps in Visual Studio. If this fails for any reason, you'll have to download and extract the package yourself, either by executing the script in<br />
<br />
tools/scripts/download_windeps.ps1<br />
<br />
or by downloading the 7-zipped packages from the following URL (you can [http://www.7-zip.org get 7-zip here]):<br />
<br />
https://github.com/codereader/DarkRadiant_WinDeps/releases/latest<br />
<br />
Download and extract it directly to the directory you cloned the sources to. The resulting folder structure should look like this. <br />
<br />
[[Image:Dr_windeps_repo.png|200px]]<br />
<br />
'''Important:''' The w32deps/ and w64deps/ folder must be in the same folder as the radiant/ or include/ folder.<br />
<br />
= (Optional) Compiling the Windows Dependencies =<br />
This step is optional and more advanced. You won't need to do this if you just want to compile and run DarkRadiant using the currently maintained version of Visual Studio.<br />
<br />
Note: in the past DarkRadiant was linking against a few boost libraries requiring static libraries, this is no longer the case since August 2017.<br />
<br />
== Compile the support libraries ==<br />
DarkRadiant is using a lot of third-party libraries like libxml2, libiconv, vorbis, etc.<br />
<br />
For Windows I set up custom VC++ solutions to compile most of the libraries directly from the source (as many of those third-party projects don't offer Windows x64 binaries), these projects can be found in the <tt>winbuild</tt> folder in Git. The winbuild folder contains all the sources needed to build the Win32/Win64 dependency binaries. Note that the headers are stored in w32deps, as the main DarkRadiant project needs them there, so w32deps is the place to look for most of the shared headers.<br />
<br />
The VC++ project files can be found in the winbuild/msvc folder. To check out the repo, go ahead like this:<br />
<br />
# Right-click your C:\Games folder >> Git Clone...<br />
# Select https://github.com/codereader/DarkRadiant_WinDeps.git to C:\Games\DarkRadiant_WinDeps<br />
<br />
or by using the git command line<br />
<br />
# git clone https://github.com/codereader/DarkRadiant_WinDeps.git C:\Games\DarkRadiant_WinDeps<br />
<br />
== Program Database Files (.pdb) ==<br />
When debugging a DarkRadiant crashdump, you'll need the program database files to get substantial information out of it, so it's vital to save the .pdb files right after compilation, otherwise they won't match against the signatures in the crashdump.<br />
<br />
As far as the windeps dependencies are concerned, I've zipped up all the .pdb files and stored them on the GitHub release page:<br />
<br />
* VC++ 2019: https://github.com/codereader/DarkRadiant_WinDeps/releases/latest (look for windeps.pdbs.7z)<br />
<br />
== See also / Links ==<br />
* [[DarkRadiant - Compilation Guide]]<br />
* [https://visualstudio.microsoft.com/downloads/ Visual Studio 2019 Community Edition]<br />
* [[Save a Memory Dump for debugging Crashes|Information about recording crash dumps]]<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Windows&diff=28278DarkRadiant - Compiling in Windows2021-04-12T18:00:22Z<p>Greebo: /* (Optional) Compiling the Windows Dependencies */</p>
<hr />
<div>To compile the sources in Windows you will need '''Visual Studio 2019 Community Edition''' or higher. The Community Edition can be acquired for free and is able to produce both 32 Bit and 64 Bit builds. <br />
<br />
You will need a Git client to clone the sources to your machine and install the Windows dependencies package. Then you're set up to compile DarkRadiant in Visual Studio.<br />
<br />
= Install a Git Client =<br />
The main codebase is stored and maintained on github, therefore you'll need a Git client like<br />
* [http://windows.github.com/ '''Github Desktop''']<br />
* [http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git '''TortoiseGit'''] <br />
<br />
Download and install the git client into any folder of your preference. After installation it might ask to reboot your machine, as Tortoise integrates into the Explorer shell.<br />
<br />
= Download Sources and Dependencies = <br />
<br />
== Using Github Desktop ==<br />
Create your github-login, configure github desktop as desired, especially the default clone path in the options dialog. Browse to the [https://github.com/codereader/DarkRadiant github page of DarkRadiant] and click on '''Clone in Windows'''. That's it!<br />
<br />
== Using TortoiseGit ==<br />
To prepare the source download, open Windows Explorer and create the folder you want to clone (i.e. download) the sources into. Make sure the folder does not contain spaces. Use your Git client to clone the DarkRadiant repository from github:<br />
<br />
Make sure the '''recursive''' flag is checked in the dialog.<br />
<br />
[[Image:dr git clone.png|200px]]<br />
<br />
Cloning takes a minute or two - after the process is finished your folder should be looking like this:<br />
<br />
[[Image:Dr_bare_repo.png|200px]]<br />
<br />
= Compile =<br />
Start Visual Studio and open the DarkRadiant solution file (.sln) which is ready for you in the <tt>tools/msvc</tt> folder. <br />
<br />
To build a package for the x64 target, make sure to select the ''x64'' platform from the configuration manager's dropdown box (located in Visual Studio's toolbar). If you prefer a 32 bit build, select the Win32 target. <br />
<br />
Select ''release'' build (unless you want to debug a problem) and hit Ctrl-Shift-B in VC++ to start building the sources or select "Build > Build Solution" from the menus.<br />
<br />
{{important|headline=Note|text=If you cloned the sources to <tt>C:\Games\DarkRadiant</tt>, the application binary will be placed in <tt>C:\Games\DarkRadiant\install\DarkRadiant.exe</tt>}}<br />
<br />
The project output files are set up in a way to automatically install the binaries in the <tt>install/</tt>, <tt>install/modules/</tt> and <tt>install/plugins/</tt> folders. Also, all dependencies from the w32deps/ folder (see previous section) are automatically copied to the install/ folder during the post-build event. If anything goes wrong during compilation, please seek help in the [http://forums.thedarkmod.com/forum/51-darkradiant-feedback-and-development/ forums].<br />
<br />
The build expects the w32deps folder to be located alongside the sources, especially x64 builds expect the w64deps folder to be sitting next to it. See above for how to set up the folders in case you missed that step. For both platforms the output will be placed in the same install/ directory.<br />
<br />
== Manual Download of the Dependencies Package ==<br />
For Windows builds additional dependencies are automatically downloaded and copied into the source tree by the build steps in Visual Studio. If this fails for any reason, you'll have to download and extract the package yourself, either by executing the script in<br />
<br />
tools/scripts/download_windeps.ps1<br />
<br />
or by downloading the 7-zipped packages from the following URL (you can [http://www.7-zip.org get 7-zip here]):<br />
<br />
https://github.com/codereader/DarkRadiant_WinDeps/releases/latest<br />
<br />
Download and extract it directly to the directory you cloned the sources to. The resulting folder structure should look like this. <br />
<br />
[[Image:Dr_windeps_repo.png|200px]]<br />
<br />
'''Important:''' The w32deps/ and w64deps/ folder must be in the same folder as the radiant/ or include/ folder.<br />
<br />
= (Optional) Compiling the Windows Dependencies =<br />
This step is optional and more advanced. You won't need to do this if you just want to compile and run DarkRadiant using the currently maintained version of Visual Studio.<br />
<br />
Note: in the past DarkRadiant was linking against a few boost libraries requiring static libraries, this is no longer the case since August 2017.<br />
<br />
== Compile the support libraries ==<br />
DarkRadiant is using a lot of third-party libraries like libxml2, libiconv, vorbis, etc.<br />
<br />
For Windows I set up custom VC++ solutions to compile most of the libraries directly from the source (as many of those third-party projects don't offer Windows x64 binaries), these projects can be found in the <tt>winbuild</tt> folder in Git. The winbuild folder contains all the sources needed to build the Win32/Win64 dependency binaries. Note that the headers are stored in w32deps, as the main DarkRadiant project needs them there, so w32deps is the place to look for most of the shared headers.<br />
<br />
The VC++ project files can be found in the winbuild/msvc folder. To check out the repo, go ahead like this:<br />
<br />
# Right-click your C:\Games folder >> Git Clone...<br />
# Select https://github.com/codereader/DarkRadiant_WinDeps.git to C:\Games\DarkRadiant_WinDeps<br />
<br />
or by using the git command line<br />
<br />
# git clone https://github.com/codereader/DarkRadiant_WinDeps.git C:\Games\DarkRadiant_WinDeps<br />
<br />
== Program Database Files (.pdb) ==<br />
When debugging a DarkRadiant crashdump, you'll need the program database files to get substantial information out of it, so it's vital to save the .pdb files right after compilation, otherwise they won't match against the signatures in the crashdump.<br />
<br />
As far as the windeps dependencies are concerned, I've zipped up all the .pdb files and stored them on the GitHub release page:<br />
<br />
* VC++ 2019: https://github.com/codereader/DarkRadiant/releases/download/2.10.0/windeps.pdbs.7z<br />
<br />
== See also / Links ==<br />
* [[DarkRadiant - Compilation Guide]]<br />
* [https://visualstudio.microsoft.com/downloads/ Visual Studio 2019 Community Edition]<br />
* [[Save a Memory Dump for debugging Crashes|Information about recording crash dumps]]<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Windows&diff=28277DarkRadiant - Compiling in Windows2021-04-12T17:58:06Z<p>Greebo: /* Download Sources and Dependencies */</p>
<hr />
<div>To compile the sources in Windows you will need '''Visual Studio 2019 Community Edition''' or higher. The Community Edition can be acquired for free and is able to produce both 32 Bit and 64 Bit builds. <br />
<br />
You will need a Git client to clone the sources to your machine and install the Windows dependencies package. Then you're set up to compile DarkRadiant in Visual Studio.<br />
<br />
= Install a Git Client =<br />
The main codebase is stored and maintained on github, therefore you'll need a Git client like<br />
* [http://windows.github.com/ '''Github Desktop''']<br />
* [http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git '''TortoiseGit'''] <br />
<br />
Download and install the git client into any folder of your preference. After installation it might ask to reboot your machine, as Tortoise integrates into the Explorer shell.<br />
<br />
= Download Sources and Dependencies = <br />
<br />
== Using Github Desktop ==<br />
Create your github-login, configure github desktop as desired, especially the default clone path in the options dialog. Browse to the [https://github.com/codereader/DarkRadiant github page of DarkRadiant] and click on '''Clone in Windows'''. That's it!<br />
<br />
== Using TortoiseGit ==<br />
To prepare the source download, open Windows Explorer and create the folder you want to clone (i.e. download) the sources into. Make sure the folder does not contain spaces. Use your Git client to clone the DarkRadiant repository from github:<br />
<br />
Make sure the '''recursive''' flag is checked in the dialog.<br />
<br />
[[Image:dr git clone.png|200px]]<br />
<br />
Cloning takes a minute or two - after the process is finished your folder should be looking like this:<br />
<br />
[[Image:Dr_bare_repo.png|200px]]<br />
<br />
= Compile =<br />
Start Visual Studio and open the DarkRadiant solution file (.sln) which is ready for you in the <tt>tools/msvc</tt> folder. <br />
<br />
To build a package for the x64 target, make sure to select the ''x64'' platform from the configuration manager's dropdown box (located in Visual Studio's toolbar). If you prefer a 32 bit build, select the Win32 target. <br />
<br />
Select ''release'' build (unless you want to debug a problem) and hit Ctrl-Shift-B in VC++ to start building the sources or select "Build > Build Solution" from the menus.<br />
<br />
{{important|headline=Note|text=If you cloned the sources to <tt>C:\Games\DarkRadiant</tt>, the application binary will be placed in <tt>C:\Games\DarkRadiant\install\DarkRadiant.exe</tt>}}<br />
<br />
The project output files are set up in a way to automatically install the binaries in the <tt>install/</tt>, <tt>install/modules/</tt> and <tt>install/plugins/</tt> folders. Also, all dependencies from the w32deps/ folder (see previous section) are automatically copied to the install/ folder during the post-build event. If anything goes wrong during compilation, please seek help in the [http://forums.thedarkmod.com/forum/51-darkradiant-feedback-and-development/ forums].<br />
<br />
The build expects the w32deps folder to be located alongside the sources, especially x64 builds expect the w64deps folder to be sitting next to it. See above for how to set up the folders in case you missed that step. For both platforms the output will be placed in the same install/ directory.<br />
<br />
= (Optional) Compiling the Windows Dependencies =<br />
This step is optional and more advanced. You won't need to do this if you just want to compile and run DarkRadiant using the currently maintained version of Visual Studio.<br />
<br />
Note: in the past DarkRadiant was linking against a few boost libraries requiring static libraries, this is no longer the case since August 2017.<br />
<br />
== Compile the support libraries ==<br />
DarkRadiant is using a lot of third-party libraries like libxml2, libiconv, vorbis, etc.<br />
<br />
For Windows I set up custom VC++ solutions to compile most of the libraries directly from the source (as many of those third-party projects don't offer Windows x64 binaries), these projects can be found in the <tt>winbuild</tt> folder in Git. The winbuild folder contains all the sources needed to build the Win32/Win64 dependency binaries. Note that the headers are stored in w32deps, as the main DarkRadiant project needs them there, so w32deps is the place to look for most of the shared headers.<br />
<br />
The VC++ project files can be found in the winbuild/msvc folder. To check out the repo, go ahead like this:<br />
<br />
# Right-click your C:\Games folder >> Git Clone...<br />
# Select https://github.com/codereader/DarkRadiant_WinDeps.git to C:\Games\DarkRadiant_WinDeps<br />
<br />
or by using the git command line<br />
<br />
# git clone https://github.com/codereader/DarkRadiant_WinDeps.git C:\Games\DarkRadiant_WinDeps<br />
<br />
== Program Database Files (.pdb) ==<br />
When debugging a DarkRadiant crashdump, you'll need the program database files to get substantial information out of it, so it's vital to save the .pdb files right after compilation, otherwise they won't match against the signatures in the crashdump.<br />
<br />
As far as the windeps dependencies are concerned, I've zipped up all the .pdb files and stored them on the GitHub release page:<br />
<br />
* VC++ 2019: https://github.com/codereader/DarkRadiant/releases/download/2.10.0/windeps.pdbs.7z<br />
<br />
== See also / Links ==<br />
* [[DarkRadiant - Compilation Guide]]<br />
* [https://visualstudio.microsoft.com/downloads/ Visual Studio 2019 Community Edition]<br />
* [[Save a Memory Dump for debugging Crashes|Information about recording crash dumps]]<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Windows&diff=28276DarkRadiant - Compiling in Windows2021-04-12T17:57:37Z<p>Greebo: /* Using TortoiseGit */</p>
<hr />
<div>To compile the sources in Windows you will need '''Visual Studio 2019 Community Edition''' or higher. The Community Edition can be acquired for free and is able to produce both 32 Bit and 64 Bit builds. <br />
<br />
You will need a Git client to clone the sources to your machine and install the Windows dependencies package. Then you're set up to compile DarkRadiant in Visual Studio.<br />
<br />
= Install a Git Client =<br />
The main codebase is stored and maintained on github, therefore you'll need a Git client like<br />
* [http://windows.github.com/ '''Github Desktop''']<br />
* [http://code.google.com/p/msysgit/downloads/list?q=full+installer+official+git '''TortoiseGit'''] <br />
<br />
Download and install the git client into any folder of your preference. After installation it might ask to reboot your machine, as Tortoise integrates into the Explorer shell.<br />
<br />
= Download Sources and Dependencies = <br />
<br />
== Using Github Desktop ==<br />
Create your github-login, configure github desktop as desired, especially the default clone path in the options dialog. Browse to the [https://github.com/codereader/DarkRadiant github page of DarkRadiant] and click on '''Clone in Windows'''. That's it!<br />
<br />
== Using TortoiseGit ==<br />
To prepare the source download, open Windows Explorer and create the folder you want to clone (i.e. download) the sources into. Make sure the folder does not contain spaces. Use your Git client to clone the DarkRadiant repository from github:<br />
<br />
Make sure the '''recursive''' flag is checked in the dialog.<br />
<br />
[[Image:dr git clone.png|200px]]<br />
<br />
Cloning takes a minute or two - after the process is finished your folder should be looking like this:<br />
<br />
[[Image:Dr_bare_repo.png|200px]]<br />
<br />
== Download the Dependencies Package ==<br />
For Windows builds additional dependencies must be downloaded and copied into the source tree. To keep the github source repository small, the dependencies can be downloaded as 7-zipped packages (you can [http://www.7-zip.org get 7-zip here]):<br />
<br />
https://github.com/codereader/DarkRadiant/releases/download/2.7.0/windeps.7z<br />
<br />
Download and extract it directly to the directory you cloned the sources to. The resulting folder structure should look like this. <br />
<br />
[[Image:Dr_windeps_repo.png|200px]]<br />
<br />
'''Important:''' The w32deps/ and w64deps/ folder must be in the same folder as the radiant/ or include/ folder.<br />
<br />
= Compile =<br />
Start Visual Studio and open the DarkRadiant solution file (.sln) which is ready for you in the <tt>tools/msvc</tt> folder. <br />
<br />
To build a package for the x64 target, make sure to select the ''x64'' platform from the configuration manager's dropdown box (located in Visual Studio's toolbar). If you prefer a 32 bit build, select the Win32 target. <br />
<br />
Select ''release'' build (unless you want to debug a problem) and hit Ctrl-Shift-B in VC++ to start building the sources or select "Build > Build Solution" from the menus.<br />
<br />
{{important|headline=Note|text=If you cloned the sources to <tt>C:\Games\DarkRadiant</tt>, the application binary will be placed in <tt>C:\Games\DarkRadiant\install\DarkRadiant.exe</tt>}}<br />
<br />
The project output files are set up in a way to automatically install the binaries in the <tt>install/</tt>, <tt>install/modules/</tt> and <tt>install/plugins/</tt> folders. Also, all dependencies from the w32deps/ folder (see previous section) are automatically copied to the install/ folder during the post-build event. If anything goes wrong during compilation, please seek help in the [http://forums.thedarkmod.com/forum/51-darkradiant-feedback-and-development/ forums].<br />
<br />
The build expects the w32deps folder to be located alongside the sources, especially x64 builds expect the w64deps folder to be sitting next to it. See above for how to set up the folders in case you missed that step. For both platforms the output will be placed in the same install/ directory.<br />
<br />
= (Optional) Compiling the Windows Dependencies =<br />
This step is optional and more advanced. You won't need to do this if you just want to compile and run DarkRadiant using the currently maintained version of Visual Studio.<br />
<br />
Note: in the past DarkRadiant was linking against a few boost libraries requiring static libraries, this is no longer the case since August 2017.<br />
<br />
== Compile the support libraries ==<br />
DarkRadiant is using a lot of third-party libraries like libxml2, libiconv, vorbis, etc.<br />
<br />
For Windows I set up custom VC++ solutions to compile most of the libraries directly from the source (as many of those third-party projects don't offer Windows x64 binaries), these projects can be found in the <tt>winbuild</tt> folder in Git. The winbuild folder contains all the sources needed to build the Win32/Win64 dependency binaries. Note that the headers are stored in w32deps, as the main DarkRadiant project needs them there, so w32deps is the place to look for most of the shared headers.<br />
<br />
The VC++ project files can be found in the winbuild/msvc folder. To check out the repo, go ahead like this:<br />
<br />
# Right-click your C:\Games folder >> Git Clone...<br />
# Select https://github.com/codereader/DarkRadiant_WinDeps.git to C:\Games\DarkRadiant_WinDeps<br />
<br />
or by using the git command line<br />
<br />
# git clone https://github.com/codereader/DarkRadiant_WinDeps.git C:\Games\DarkRadiant_WinDeps<br />
<br />
== Program Database Files (.pdb) ==<br />
When debugging a DarkRadiant crashdump, you'll need the program database files to get substantial information out of it, so it's vital to save the .pdb files right after compilation, otherwise they won't match against the signatures in the crashdump.<br />
<br />
As far as the windeps dependencies are concerned, I've zipped up all the .pdb files and stored them on the GitHub release page:<br />
<br />
* VC++ 2019: https://github.com/codereader/DarkRadiant/releases/download/2.10.0/windeps.pdbs.7z<br />
<br />
== See also / Links ==<br />
* [[DarkRadiant - Compilation Guide]]<br />
* [https://visualstudio.microsoft.com/downloads/ Visual Studio 2019 Community Edition]<br />
* [[Save a Memory Dump for debugging Crashes|Information about recording crash dumps]]<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&diff=28275DarkRadiant - Compiling in Linux2021-04-12T17:56:38Z<p>Greebo: /* Ubuntu 20.04 and later */</p>
<hr />
<div>== Install Required Packages ==<br />
<br />
=== Ubuntu 20.04 and later ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git g++ gettext cmake pkg-config zlib1g-dev libjpeg-dev libxml2-dev libsigc++-2.0-dev libgtest-dev libeigen-dev<br />
sudo apt-get install libwxgtk3.0-gtk3-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== openSUSE Tumbleweed ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo zypper install git cmake gcc-c++ gettext-tools zlib-devel libjpeg62-devel libxml2-devel libsigc++2-devel gtest<br />
sudo zypper install wxWidgets-3_0-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python38-devel<br />
<br />
=== Mageia 8 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo urpmi git cmake make gcc-c++ libzlib-devel libjpeg-devel libwxgtku3.0-devel libsigc++2.0-devel <br />
sudo urpmi libftgl-devel libglew-devel libpython3-devel libopenal-devel libfreealut-devel libvorbis-devel lib64gtest-devel<br />
<br />
=== Debian 10 ===<br />
<br />
Copy and paste the following into a terminal:<br />
<br />
sudo apt-get install git cmake pkg-config gettext zlib1g-dev libjpeg-dev libwxgtk3.0-dev libgtest-dev<br />
sudo apt-get install libxml2-dev libsigc++-2.0-dev libpng-dev libftgl-dev libglew-dev libalut-dev libvorbis-dev python3-dev<br />
<br />
=== Fedora 26 / 25 ===<br />
Copy and paste the following into a terminal:<br />
<br />
sudo dnf install git automake libtool gcc-c++ zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel libsigc++20-devel <br />
sudo dnf install libpng12-devel ftgl-devel glew-devel libvorbis-devel freealut-devel python-devel pybind11-devel<br />
<br />
Note that the wxGTK package does not yet support Wayland environments, which is the default since Fedora 25 (DarkRadiant will just segfault during startup). You'll need to [https://fedoraproject.org/wiki/Changes/WaylandByDefault deactivate it] for the moment being.<br />
<br />
=== Arch Linux ===<br />
The following packages are requred after starting from an Anarchy installation using Gnome as Window Manager. <br />
<br />
sudo pacman -S cmake wxgtk ftgl glew freealut<br />
<br />
=== CentOS 7 x64 ===<br />
<br />
Copy and paste the following into a terminal, run as user who has the required permissions to install the packages:<br />
<br />
sudo yum -y install gcc gcc-c++ git automake libtool zlib-devel libjpeg-turbo-devel wxGTK3-devel libxml2-devel <br />
sudo yum -y install libsigc++20-devel ftgl-devel glew-devel boost-devel openal-soft-devel freealut-devel libvorbis-devel python-devel<br />
<br />
CentOS 7 ships with an older compiler, so you'll need to install a more recent GCC first (following the directions on [https://stackoverflow.com/questions/36327805/how-to-install-gcc-5-3-with-yum-on-centos-7-2 stackoverflow]):<br />
<br />
sudo yum install centos-release-scl <br />
sudo yum install devtoolset-4-gcc*<br />
scl enable devtoolset-4 bash<br />
<br />
Note that the <tt>wxGTK3-devel</tt> package doesn't create a <tt>wx-config</tt> symlink in the <tt>/usr/bin</tt> directory, that's why you need to pass an additional <tt>--with-wx-config=/usr/bin/wx-config-3.0</tt> argument to the ./configure script below, like this:<br />
<br />
./configure --enable-darkmod-plugins --with-wx-config=/usr/bin/wx-config-3.0<br />
<br />
=== Slackware 14.2 ===<br />
<br />
Slackware doesn't provide precompiled packages on the one hand (unlike Debian or Arch), but already ships with a lot of libraries on the other. Stuff like git, automake, libtools and development libraries like zlib and boost are already present, but wxWidgets, openAL, ALut and FTGL need to be installed by means of a SlackBuild script. The following has been done in Slackware 14.2, so your mileage may vary.<br />
<br />
Download the Source tarballs and the SlackBuild packages from these URLs:<br />
<br />
* https://slackbuilds.org/repository/14.2/libraries/wxGTK3/<br />
* https://slackbuilds.org/repository/14.2/libraries/ftgl/<br />
* https://slackbuilds.org/repository/14.2/libraries/OpenAL/<br />
* https://slackbuilds.org/repository/14.2/libraries/freealut/<br />
<br />
Download and extract the SlackBuild <tt>.tar.gz</tt> files in your <tt>~/Downloads</tt> folder (or anywhere else where you want to have them). For instance, the wxGTK3 package can be untar'd like this:<br />
<br />
tar xzf wxGTK3.tar.gz<br />
cd wxGTK3<br />
chmod +x wxGTK3.SlackBuild<br />
<br />
Do this for all of the above libraries, that should give you the directories <tt>ftgl/</tt>, <tt>OpenAL/</tt>, <tt>wxGTK3/</tt> and <tt>freealut/</tt>. Next, download the Source Tarballs (the <tt>.tar.bz2</tt>) files from the links above and place them next to the corresponding SlackBuild script. Then run the scripts for each of them and install the build output in your system in a second step:<br />
<br />
./wxGTK3.SlackBuild<br />
<br />
This produced (on my end at least) the package <tt>/tmp/wxGTK3-3.0.2-i486-2_SBo.tgz</tt> which can be installed by the <tt>installpkg</tt> command:<br />
<br />
installpkg /tmp/wxGTK3-3.0.2-i486-2_SBo.tgz<br />
<br />
Do the same for the rest of the libraries (ftgl, OpenAL, freealut). Be aware that the freealut package depends on the OpenAL package, so you need to do the OpenAL one first. Once you have these installed, you can proceed to the build section (<tt>git clone</tt> and <tt>configure</tt> and <tt>make</tt>).<br />
<br />
=== Gentoo ===<br />
<br />
DarkRadiant can be built and installed from an unofficial ebuild repository (overlay). The easiest way to do this is with [https://packages.gentoo.org/packages/app-portage/layman app-portage/layman], which must be installed with the <tt>git</tt> use flag.<br />
<br />
In the 'overlays' section in <tt>/etc/layman/layman.cfg</tt>, add:<br />
<br />
https://raw.githubusercontent.com/varingst/varingst-overlay/master/overlay.xml<br />
<br />
Then fetch and add the overlay:<br />
<br />
# layman -f -a varingst<br />
<br />
Now that the overlay is added, you can build and install DarkRadiant with Portage:<br />
<br />
# emerge darkradiant<br />
<br />
To sync the overlay, either do it manually with layman:<br />
<br />
# layman -s varingst<br />
<br />
Or look into the [https://wiki.gentoo.org/wiki/Project:Portage/Sync various ways to hook into the portage sync system].<br />
<br />
=== Building with a non-default g++ Compiler ===<br />
DarkRadiant's codebase makes use of C++17 features, in particular std::filesystem. Not all distributions ship with a compatible g++ compiler by default, but it's possible to install a more recent compiler suite. Get the compiler package and ensure that the makefiles are called with the correct setup, e.g.<br />
CXX="g++-5.1" cmake . && make && make install<br />
<br />
=== Older Distributions / Compiling DarkRadiant 1.8 and older ===<br />
The instructions about how to compile DR 1.8 (based on GTK) in distributions published in 2012 and older have been removed. They should still be in the [http://wiki.thedarkmod.com/index.php?title=DarkRadiant_-_Compiling_in_Linux&oldid=18927 history] of this page, should they ever be needed.<br />
<br />
== Obtain the source ==<br />
<br />
Make sure you have the git client installed, this is covered in the package installation commands above. <br />
Next, change to the directory where you want the source code to be in and then clone the Git repository with:<br />
<br />
git clone git://github.com/codereader/DarkRadiant.git --recurse-submodules<br />
<br />
Once the initial clone is done, the source can be updated to the latest version from inside the working directory with:<br />
<br />
git pull<br />
<br />
== Configure and Compile ==<br />
DarkRadiant employs the CMake build system under Linux as used in many open-source projects. Make sure you have the CMake toolchain downloaded, this is covered in the package installation commands above.<br />
<br />
To build DarkRadiant, run the typical chain of CMake and make commands:<br />
<br />
cmake .<br />
make<br />
[sudo] make install<br />
<br />
By the above, a release build will be created; if a debug build is required pass the <tt>-DCMAKE_BUILD_TYPE=Debug</tt> option to the cmake command script.<br />
<br />
Other points to note about the configure process:<br />
<br />
* The DarkMod-specific plugins are built by default, the <tt>-DENABLE_DM_PLUGINS=OFF</tt> argument will disable them.<br />
* The CMake script autodetects required dependencies, and will conditionally enable optional components of DarkRadiant (such as the sound plugin) based on what it finds.<br />
* For quick testing of a DarkRadiant build, it is desirable to install it into a temporary location rather than the default of <tt>/usr/local</tt>; for this, simply pass a prefix option such as <tt>-DCMAKE_INSTALL_PREFIX=/tmp/dr</tt> to cmake, after which DarkRadiant will be installed in <tt>/tmp/dr/bin/darkradiant</tt>.<br />
<br />
=== Multiprocessor Systems ===<br />
<br />
You can pass the <tt>--jobs=N</tt> parameter to make:<br />
make --jobs=2<br />
to use more than one processor for the compilation. This will eat lots of RAM, so don't do this on machines with little available memory.<br />
<br />
=== Building a .deb package ===<br />
<br />
To build a Debian/Ubuntu package, simply run<br />
<br />
dpkg-buildpackage -rfakeroot<br />
<br />
in the main <tt>darkradiant</tt> directory. The .deb will be created in the parent directory.<br />
<br />
{{coding}}<br />
{{darkradiant|sort=Compilation}}</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28260DarkRadiant Script Reference2021-04-11T15:36:04Z<p>Greebo: /* EditableMaterialStage */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "primitive", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
* <tt>setVertexColourMode(MaterialStage.VertexColourMode mode)</tt> Sets the vertex colour mode of this stage (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Sets the clamp type of this stage, overriding the one defined in the material. (since 2.12)<br />
* <tt>setPrivatePolygonOffset(float offset)</tt> Sets the private polygon offset of this stage. (since 2.12)<br />
* <tt>setRenderMapSize(Vector2 dimensions)</tt> Sets the dimensions of the render map used by the render map expressions. (since 2.12)<br />
* <tt>setSoundMapWaveForm(bool waveForm)</tt> Sets the waveform property for stages using the soundmap expression. (since 2.12)<br />
* <tt>setVideoMapProperties(string filePath, bool looping)</tt> Sets the path and loop properties for stages using the videomap expression. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28259DarkRadiant Script Reference2021-04-11T15:00:30Z<p>Greebo: /* EditableMaterialStage */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "primitive", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
* <tt>setColourExpressionFromString(MaterialStage.ColourComponent selector, string expression)</tt> Sets the R/G/B/A/RGB/RGBA colour expression to use in this stage (since 2.12)<br />
* <tt>setConditionExpressionFromString(string expression)</tt> Sets the condition expression which enables/disables this stage depending on its value (since 2.12)<br />
* <tt>setTexGenType(MaterialStage.TexGenType type)</tt> Sets the texgen type of this stage (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>setTexGenExpressionFromString(int index, string expression)</tt> Sets one of the three texgen expressions used in the wobble sky texgen type (index in [0..2]) (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28258DarkRadiant Script Reference2021-04-11T14:52:25Z<p>Greebo: /* EditableMaterialStage */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "primitive", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
<br />
* <tt>setMapType(MaterialStage.MapType type)</tt> Sets the map type of this stage (cubemap, map, mirrorrendermap, etc.) (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>setMapExpressionFromString(string expression)</tt> Sets the map expression (an image path, or a more complex map expression) (since 2.12)<br />
* <tt>setBlendFuncStrings(StringPair blendFuncStrings)</tt> Sets the blend func strings of this stage, passed as pair of strings, e.g. ["gl_one", "gl_zero"]. (since 2.12)<br />
* <tt>setAlphaTestExpressionFromString(string expression)</tt> Sets the alpha test expression of this stage (since 2.12)<br />
* <tt>int addTransformation(MaterialStage.TransformType type, string expression1, string expression2)</tt> Appends a new transformation to this stage with the given parameters, returning the index of the newly created slot. (since 2.12)<br />
* <tt>int updateTransformation(int index, MaterialStage.TransformType type, string expression1, string expression2)</tt> Updates an existing transformation of this stage to the given parameters. (since 2.12)<br />
* <tt>int removeTransformation(int index)</tt> Removes an existing transformation from this stage. (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28257DarkRadiant Script Reference2021-04-11T14:36:24Z<p>Greebo: /* EditableMaterialStage */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "primitive", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
<br />
=== Stage Structures and Enumerations ===<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28256DarkRadiant Script Reference2021-04-11T14:35:40Z<p>Greebo: /* Material */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "primitive", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>EditableMaterialStage getEditableStage(int index)</tt> Returns the editable stage with the given index (since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28255DarkRadiant Script Reference2021-04-11T14:34:53Z<p>Greebo: /* MaterialStage */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "primitive", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
=== EditableMaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the writeable one. An <tt>EditableMaterialStage</tt> offers all the functions of a read-only <tt>MaterialStage</tt> plus all the methods to change the stage properties. If you don't intend to modify a stage, consider using the read-only type returned by <tt>Material.getStage</tt> instead.<br />
<br />
* <tt>setStageFlag(MaterialStage.Flag flag)</tt> Sets the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>clearStageFlag(MaterialStage.Flag flag)</tt> Clears the given stage flag (see MaterialStage.Flag below) (since 2.12)<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28254DarkRadiant Script Reference2021-04-11T14:15:01Z<p>Greebo: /* MaterialStage */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "primitive", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>string getMapExpressionString()</tt> The map expression used to generate/define the texture of this stage (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
* <tt>float getPrivatePolygonOffset()</tt> Returns the private polygon offset of this stage(since 2.12)<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebohttps://wiki.thedarkmod.com/index.php?title=DarkRadiant_Script_Reference&diff=28253DarkRadiant Script Reference2021-04-11T14:09:32Z<p>Greebo: /* MaterialStage */</p>
<hr />
<div>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. <br />
A complete reference of all available classes can be found later in this article.<br />
<br />
If you just want to run the scripts, see here: [[Running Scripts in Darkradiant]].<br />
<br />
== Entering Script Code ==<br />
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.<br />
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.<br />
<br />
There is a '''test.py''' in DarkRadiant's scripts/ folder, which demonstrates large parts of this interface.<br />
<br />
== The 'darkradiant' Module ==<br />
<br />
All DarkRadiant classes and types are in the <tt>darkradiant</tt> module which can be imported like this<br />
import darkradiant as dr<br />
One can of course omit the <tt>as dr</tt> alias, but it's less typing this way. All the "Global*" objects like <tt>GlobalShaderSystem</tt> (see below) are already exposed to scripts. The rest needs to imported from the <tt>darkradiant</tt> module and referred to by the prefix "dr".<br />
<br />
== Classes and Methods ==<br />
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.<br />
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.<br />
<br />
=== GlobalSceneGraph ===<br />
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.<br />
<br />
* <tt>SceneNode root()</tt> 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.<br />
<br />
=== SceneNode ===<br />
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.<br />
Each SceneNode can act as parent (or container) to one or many SceneNodes, but each SceneNode can only have one parent at a time. <br />
The methods of a general SceneNode are as follows:<br />
<br />
* <tt>isNull()</tt> 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.<br />
* <tt>addToContainer(SceneNode newContainer)</tt> Adds this node as child to the given container.<br />
* <tt>removeFromParent()</tt> Removes this node from any parent container. If this node has no parent, nothing happens.<br />
* <tt>AABB getWorldAABB()</tt> Returns the bounding box (absolute coordinates) of this node. This includes the bounding boxes of all child nodes as well.<br />
* <tt>SceneNode getParent()</tt> Returns the parent of this node. If this node doesn't have a parent, a NULL node is returned.<br />
* <tt>string getNodeType()</tt> Returns the type string of this node. Possible values: "map", "entity", "primitive", "unknown"<br />
* <tt>traverse(SceneNodeVisitor visitor)</tt> Traverses this Node and all its children using the given Visitor object. See the tutorial about scenegraph traversal for more information.<br />
* <tt>traverseChildren(SceneNodeVisitor visitor)</tt> 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)<br />
* <tt>setSelected(bool isSelected)</tt> Sets the selection status of this node, i.e. setSelected(1) will select this node. Not all nodes are selectable (ModelNodes, for example).<br />
* <tt>invertSelected()</tt> 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.<br />
* <tt>bool isSelected()</tt> Returns the selection status of this node. A return value true means that this node is selected.<br />
<br />
=== SceneGraph Traversal ===<br />
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.<br />
<br />
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.<br />
<br />
This is a working code example where a visitor will traverse the entire scenegraph (i.e. a whole map):<br />
import darkradiant as dr<br />
<br />
# This is the visitor object<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print(node.getNodeType())<br />
return 1<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
<br />
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).<br />
When this scenegraph is traversed (starting from the root), the visitor will produce the following output:<br />
entity<br />
primitive<br />
primitive<br />
entity<br />
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.<br />
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:<br />
import darkradiant as dr<br />
<br />
# This visitor will NOT traverse children of entities<br />
class EntityWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Check whether we have an entity<br />
if node.isEntity():<br />
# ...<br />
# do something with this entity<br />
# ...<br />
return 0 # return false: don't traverse entities<br />
else:<br />
return 1 # not an entity, return true to traverse children<br />
<br />
# Instantiate a new entity walker object<br />
walker = EntityWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
The output will be something like this:<br />
entity<br />
entity<br />
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. <br />
When the '''post''' function is defined, it will be invoked ''after'' the walker has finished traversing a node's children. This is an example:<br />
import darkradiant as dr<br />
<br />
# This visitor has both pre and post functions defined<br />
class SceneWalker(dr.SceneNodeVisitor) :<br />
def pre(self, node):<br />
# Print the type string of each visited node<br />
print('Pre: ' + node.getNodeType())<br />
return 1<br />
def post(self, node):<br />
# Print the type string of each visited node<br />
print('Post: ' + node.getNodeType())<br />
<br />
# Instantiate a new walker object<br />
walker = SceneWalker()<br />
GlobalSceneGraph.root().traverse(walker)<br />
Using this walker, the output will be something like this:<br />
Pre: entity<br />
Pre: primitive<br />
Post: primitive<br />
Pre: primitive<br />
Post: primitive<br />
Post: entity<br />
Pre: entity<br />
Post: entity<br />
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.<br />
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.<br />
<br />
=== Special SceneNode Types ===<br />
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.<br />
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:<br />
if node.isBrush():<br />
print('Node is a brush!')<br />
else:<br />
print('Node is not a brush.')<br />
If you want actually ''do'' something with a brush, more than just confirming its type, you'll want to go with this code:<br />
brush = node.getBrush()<br />
if not brush.isNull():<br />
# We've successfully converted the SceneNode into a BrushNode<br />
print('Found a brush with ' + str(brush.getNumFaces()) + ' faces')<br />
else:<br />
print('Node is not a brush')<br />
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.<br />
<br />
There exist analogous methods for entities, models and patches, they are called:<br />
* <tt>isEntity()</tt><br />
* <tt>EntityNode getEntity()</tt><br />
<br />
* <tt>isPatch()</tt><br />
* <tt>PatchNode getPatch()</tt><br />
<br />
* <tt>isModel()</tt><br />
* <tt>ModelNode getModel()</tt><br />
<br />
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.<br />
<br />
==== BrushNode ====<br />
* <tt>int getNumFaces()</tt> Returns the number of faces of this brush.<br />
* <tt>Face getFace(int faceIndex)</tt> Returns the face with the given index (see below for further description about a <tt>Face</tt>).<br />
* <tt>bool empty()</tt> returns true (1) if this brush has no faces.<br />
* <tt>bool hasContributingFaces()</tt> Returns true (1) if this brush has contributing (non-degenerate) faces.<br />
* <tt>removeEmptyFaces()</tt> removes degenerate faces.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of all faces of this brush.<br />
* <tt>bool hasShader(string shaderName)</tt> Returns true (1) if one or more faces of this brush carries the given shader.<br />
* <tt>bool hasVisibleMaterial()</tt> Returns true (1) if one or more faces of this brush carry a visible shader (since 1.3.2).<br />
* <tt>undoSave()</tt> Saves the current state of this brush to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>getDetailFlag()</tt> Returns the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural''). (since 1.8.1)<br />
* <tt>setDetailFlag(BrushDetailFlag)</tt> Sets the detail/structural flag for this brush (Values: ''BrushDetailFlag.Detail'' and ''BrushDetailFlag.Structural'') (since 1.8.1).<br />
<br />
===== Face =====<br />
* <tt>undoSave()</tt> Saves the current state of this face to the UndoSystem's stack, call this before manipulating it.<br />
* <tt>setShader(string newShader)</tt> Sets the shader of this face.<br />
* <tt>string getShader()</tt> Returns the shader name of this face.<br />
* <tt>shiftTexdef(s,t)</tt> shifts the texture of this face by s,t in texture space.<br />
* <tt>scaleTexdef(s_scale, t_scale)</tt> scales the tex def by the given factors in texture space.<br />
* <tt>rotateTexdef(float angle)</tt> rotates the texture by the given angle.<br />
* <tt>fitTexture(s_repeat, t_repeat)</tt> fits the texture to this face, so that it repeats the given amount of times.<br />
* <tt>flipTexture(int axis)</tt> flips the texture by the given flipAxis (0 == x-axis, 1 == y-axis)<br />
* <tt>normaliseTexture()</tt> This translates the texture as much towards the origin in texture space as possible without changing the world appearance.<br />
* <tt>Winding getWinding()</tt> Get read access to this Face's <tt>Winding</tt> object (see below).<br />
<br />
===== Winding =====<br />
A winding holds the vertices of a face. It can be enumerated using a foreach loop, whereas each element is of type <tt>WindingVertex</tt>. The WindingVertex members are as below, read-only:<br />
* <tt>Vector3 vertex</tt> the 3D coordinates of the point<br />
* <tt>Vector2 texcoord</tt> the UV coordinates<br />
* <tt>Vector3 tangent</tt> the tangent<br />
* <tt>Vector3 bitangent</tt> the bitangent<br />
* <tt>Vector3 normal</tt> the normal vector<br />
* <tt>unsigned adjacent</tt> the index of the adjacent WindingVertex<br />
<br />
==== PatchNode ====<br />
* <tt>setDims(unsigned width, unsigned height)</tt> sets the new patch dimensions.<br />
* <tt>int getWidth()</tt> returns the patch width (number of columns), returns -1 if the object is not a patch.<br />
* <tt>int getHeight()</tt> returns the patch height (number of rows), returns -1 if the object is not a patch.<br />
* <tt>PatchControl ctrlAt(unsigned row, unsigned col)</tt> returns the PatchControl structure for row (h) and col (w). See below for a PatchControl description.<br />
* <tt>string getShader()</tt> Returns the shader name for this patch.<br />
* <tt>setShader(string newShaderName)</tt> Sets the shader name for this patch.<br />
* <tt>bool hasVisibleMaterial()</tt> returns true (1) if the patch has a visible material assigned to it, false otherwise (since 1.3.2).<br />
* <tt>insertColumns(unsigned colIndex)</tt> Inserts two columns before and after the column with index <colIndex>. <br />
* <tt>insertRows(unsigned rowIndex)</tt> Inserts two rows before and after the row with index <rowIndex>.<br />
* <tt>removePoints(bool columns, unsigned index)</tt> Removes columns or rows right before and after the col/row with the given index, reducing the according dimension by 2.<br />
* <tt>appendPoints(bool columns, bool beginning)</tt> Appends two rows or columns at the beginning or the end.<br />
* <tt>bool isValid()</tt> Check if the patch has invalid control points or width/height are zero<br />
* <tt>bool isDegenerate()</tt> Check whether all control vertices are in the same 3D spot (with minimal tolerance)<br />
* <tt>bool subdivionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) - Note: the typo is actually there<br />
* <tt>bool subdivisionsFixed()</tt> Gets whether this patch is a patchDef3 (fixed tesselation) (since 2.0.5)<br />
* <tt>Subdivisions getSubdivisions()</tt> Returns the x,y subdivision values (for tesselation), see Subdivision for a further description of the return value<br />
* <tt>setFixedSubdivisions(bool isFixed, Subdivisions divisions)</tt> 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.<br />
* <tt>controlPointsChanged()</tt> Updates the patch tesselation matrix, call this everytime you're done with your PatchControl changes.<br />
* <tt>PatchMesh getTesselatedPatchMesh()</tt> 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).<br />
<br />
===== PatchMesh =====<br />
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:<br />
* <tt>width</tt> the width of the tesselated matrix.<br />
* <tt>height</tt> the height of the tesselated matrix.<br />
* <tt>vertices</tt> 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 <tt>w,h</tt> can be directly accessed using <tt>vertices[h*width + w]</tt>.<br />
<br />
===== PatchMeshVertex =====<br />
A PatchMeshVertex contains information about a single vertex of the patch mesh returned by getTesselatedPatchMesh(). It has three members:<br />
* <tt>Vector3 vertex</tt> the 3D point of this vertex.<br />
* <tt>Vector2 texcoord</tt> the UV coordinates.<br />
* <tt>Vector3 normal</tt> the normal vector.<br />
<br />
===== PatchControl =====<br />
A PatchControl is a structure containing information about a patch vertex. It has the following members:<br />
* <tt>vertex</tt> This is a vector holding the 3D coordinates of this control point, see Vector3.<br />
* <tt>texcoord</tt> This is a vector holding the 2D texture coordinates of this control point, see Vector2.<br />
<br />
===== Subdivisions =====<br />
This is a two-component vector holding two unsigned integers, defining the number of horizontal/vertical tesselations for this patch.<br />
* <tt>x</tt> The number of horizontal subdivisions, e.g. ''patch.getSubdivisions().x()''<br />
* <tt>y</tt> The number of vertical subdivisions, e.g. ''patch.getSubdivisions().y()''<br />
<br />
==== EntityNode ====<br />
* <tt>string getKeyValue(string key)</tt> Returns the value of the given entity key (=spawnarg).<br />
* <tt>setKeyValue(string key, string value)</tt> Sets the value of the named key, i.e. ''setKeyValue('health', '100')''.<br />
* <tt>forEachKeyValue(EntityVisitor visitor)</tt> Iterates over all spawnargs of this entity. This requires an EntityVisitor object, which will visit all spawnargs (see below).<br />
* <tt>bool isModel()</tt> Returns true if this entity is a model.<br />
* <tt>bool isOfType(string className)</tt> 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).<br />
* <tt>bool isInherited(string key)</tt> Returns true (1) when the given key is an inherited one.<br />
* <tt>EntityClass getEntityClass()</tt> Returns the reference to the EntityClass (the object representing the entityDef) of this entity.<br />
* <tt>EntityKeyValuePairs getKeyValuePairs(string prefix)</tt> Returns a list of all spawnargs on this entity matching the given prefix. This does not include inherited keyvalues.<br />
<br />
===== EntityVisitor =====<br />
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:<br />
import darkradiant as dr<br />
<br />
# This is the prototype of an EntityVisitor object<br />
class MyEntityVisitor(dr.EntityVisitor) :<br />
def visit(self, key, value):<br />
print('Worldspawn has spawnarg: ' + key + ' = ' + value)<br />
<br />
worldspawn = GlobalMap.getWorldSpawn()<br />
if not worldspawn.isNull():<br />
ev = MyEntityVisitor()<br />
<br />
# Cast the node onto an entity<br />
worldspawnent = worldspawn.getEntity()<br />
<br />
worldspawnent.forEachKeyValue(ev)<br />
<br />
==== ModelNode ====<br />
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.<br />
<br />
* <tt>string getFilename()</tt> Returns the filename (without path) of this model.<br />
* <tt>string getModelPath()</tt> Returns the VFS path which can be used to load this model from the modelcache.<br />
* <tt>int getSurfaceCount()</tt> Return the number of material surfaces on this model. Each material surface consists of a set of polygons sharing the same material.<br />
* <tt>int getVertexCount()</tt> Return the number of vertices in this model, equal to the sum of the vertex count from each surface.<br />
* <tt>int getPolyCount()</tt> Return the number of triangles in this model, equal to the sum of the triangle count from each surface.<br />
* <tt>MaterialList getActiveMaterials()</tt> 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.<br />
* <tt>ModelSurface getSurface(int surfaceIndex)</tt> Retrieve the interface of a specific surface, to get access to the surface's polygons and vertices. (since 1.5.0)<br />
<br />
===== ModelSurface =====<br />
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).<br />
* <tt>string getDefaultMaterial()</tt> Get the name of the default material for this surface, i.e. the name of the material without any skin applied.<br />
* <tt>string getActiveMaterial()</tt> Get the name of the currently mapped material (with skin applied) (since 2.6.0)<br />
* <tt>int getNumTriangles()</tt> Returns the number of tris of this surface.<br />
* <tt>int getNumVertices()</tt> Returns the number of vertices of this surface.<br />
* <tt>ArbitraryMeshVertex getVertex(int vertexIndex)</tt> Get a specific vertex of this surface, holding vertex, colour, tangent, normal, etc.<br />
* <tt>ModelPolygon getPolygon(int polygonIndex)</tt> 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.<br />
<br />
===== ArbitraryMeshVertex =====<br />
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).<br />
* <tt>Vector2 texcoord</tt> The 2D texture coordinates<br />
* <tt>Vector3 vertex</tt> The 3D coordinates<br />
* <tt>Vector3 normal</tt> The vertex normal<br />
* <tt>Vector3 tangent</tt> The tangent vector<br />
* <tt>Vector3 bitangent</tt> The bitangent vector<br />
* <tt>Vector3 colour</tt> The vertex colour<br />
<br />
===== ModelPolygon =====<br />
A model polygon is a triangle holding three ArbitraryMeshVertex structures a, b and c (since 1.5.0).<br />
* <tt>ArbitraryMeshVertex a</tt> The first vertex of this polygon<br />
* <tt>ArbitraryMeshVertex b</tt> The second vertex of this polygon<br />
* <tt>ArbitraryMeshVertex c</tt> The third vertex of this polygon<br />
<br />
=== Entity Classes ===<br />
<br />
==== GlobalEntityClassManager ====<br />
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.<br />
* <tt>EntityClass findClass(string classname)</tt> Finds an entity class by name. If the class with the given name doesn't exist, a NULL object is returned.<br />
* <tt>forEachEntityClass(EntityClassVisitor visitor)</tt> Iterates over all existing entity classes using the given visitor object.<br />
* <tt>ModelDef findModel(string modelDefName)</tt> Returns the model def with the given name. If it doesn't exist, the returned ModelDef is empty, including its name.<br />
* <tt>forEachModelDef(ModelDefVisitor visitor)</tt> Iterates over all existing model definitions using the given visitor object.<br />
<br />
(Note: <tt>forEachEntityClass</tt> has been introduced in DarkRadiant 1.7.0, it was previously named <tt>forEach</tt>)<br />
<br />
==== EntityClassVisitor ====<br />
An EntityClassVisitor can be used to iterate over all existing entityDefs. It just needs a single function definition named visit:<br />
* <tt>visit(EntityClass eclass)</tt> Is called for each known EntityClass.<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test implementing a eclass visitor interface<br />
class TestVisitor(dr.EntityClassVisitor) :<br />
def visit(self, eclass):<br />
print eclass.getAttribute('editor_usage').getValue()<br />
<br />
eclassVisitor = TestVisitor()<br />
GlobalEntityClassManager.forEachEntityClass(eclassVisitor)<br />
<br />
==== ModelDefVisitor ====<br />
A ModelDefVisitor can be used to iterate over all existing model definitions. It just needs a single function definition named visit:<br />
* <tt>visit(ModelDef modelDef)</tt> Is called for each known model declaration.<br />
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:<br />
# Test implementing a model def visitor interface<br />
class TestModelDefVisitor(ModelDefVisitor) :<br />
def visit(self, modelDef):<br />
print(modelDef.mesh)<br />
<br />
modelDefVisitor = TestModelDefVisitor()<br />
GlobalEntityClassManager.forEachModelDef(modelDefVisitor)<br />
<br />
==== EntityClass ====<br />
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:<br />
* <tt>isNull</tt> 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.<br />
* <tt>bool isOfType(string className)</tt> 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)<br />
* <tt>EntityClassAttribute getAttribute(string key)</tt> Returns the named attribute (spawnarg) of this entityclass. The returned attribute can be empty if the key is not defined.<br />
* <tt>string getDefFileName()</tt> Returns the mod-relative path to the .def file this entity class is defined in (since 2.8.1).<br />
<br />
==== EntityClassAttribute ====<br />
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.<br />
* <tt>getName()</tt> Returns the name of this attribute (i.e. the key), for example: "spawnclass".<br />
* <tt>getValue()</tt> Returns the value of this attribute.<br />
* <tt>getType()</tt> Returns the type string of this attribute - this can be "string", "bool", "sound", "float", etc.<br />
* <tt>getDescription()</tt> Returns the description, as provided by an "editor_*" spawnarg.<br />
* <tt>inherited</tt> Returns TRUE if this attribute has been inherited from a parent entityDef.<br />
<br />
(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+.)<br />
<br />
==== ModelDef ====<br />
A ModelDef represents a model {} block as defined in the .def files of the game. A ModelDef primarily contains information about meshes and animations.<br />
* <tt>name</tt> The name of this modelDef.<br />
* <tt>mesh</tt> The value of the "mesh" property, usually pointing to an .md5mesh file in TDM.<br />
* <tt>skin</tt> The skin property. This is empty if no skin is used by this model.<br />
* <tt>parent</tt> The parent def this modelDef is inheriting from.<br />
* <tt>anims</tt> The list of anims. This basically is a key => value map, which can be iterated over like shown in the following code snippet.<br />
<br />
# Try to find the modeldef of the builder forger<br />
modelDef = GlobalEntityClassManager.findModel('builderforger')<br />
print('ModelDef mesh for builderforger = ' + modelDef.mesh)<br />
<br />
# Iterate over all the animations for this modelDef<br />
for anim in modelDef.anims:<br />
print(anim.key())<br />
print(' = ')<br />
print(anim.data())<br />
print('')<br />
<br />
=== GlobalEntityCreator ===<br />
The entity creator can be used (as the name implies) to create entities in the scene.<br />
<br />
It offers two flavours (so-called overloads) of the method "createEntity":<br />
<br />
* <tt>SceneNode createEntity(string entityClassName)</tt> Create an entity of the given class, specified by name, e.g. "atdm:playertools_lantern"<br />
* <tt>SceneNode createEntity(EntityClass eclass)</tt> Create an entity of the given class, as acquired by the GlobalEntityClassManager<br />
<br />
After creation, be sure to insert the entity into some parent node, which is always the root node for idTech4 maps.<br />
<br />
=== GlobalCommandSystem ===<br />
The global command system can be used to execute DarkRadiant commands, as entered manually in the console.<br />
* <tt>execute(string command)</tt> Executes the given string command.<br />
* <tt>addStatement(string statementName, string str)</tt> Adds the given <str> as new statement with the given name.<br />
* <tt>removeCommand</tt> Removes the command with the given name from the command system.<br />
<br />
Example:<br />
# Test the commandsystem (this stretches the texture of the selection by 10%)<br />
GlobalCommandSystem.execute('texscale "0 0.1"')<br />
<br />
=== GlobalFileSystem ===<br />
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.<br />
<br />
* <tt>forEachFile(string baseDir, string extension, FileVisitor visitor, int depth)</tt> 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.<br />
* <tt>string findFile(string relativeFilename)</tt> Returns the absolute filename for the given relative filename.<br />
* <tt>string findRoot(string absFilename)</tt> Returns the filesystem root for the given absolute filename, basically converting it to a relative filename.<br />
* <tt>string readTextFile(string relativeFilename)</tt> Returns the full text contents of the given filename.<br />
* <tt>int getFileCount(string filename)</tt> Returns the number of files in the VFS matching the given filename.<br />
<br />
==== FileVisitor ====<br />
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.<br />
<br />
* <tt>visit(string filename)</tt> Is called by forEachFile() for each matching filename.<br />
<br />
=== GlobalGameManager ===<br />
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.<br />
<br />
* <tt>string getUserEnginePath()</tt> 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)<br />
* <tt>string getModPath()</tt> 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.<br />
* <tt>string getModBasePath()</tt> 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.<br />
* <tt>Game currentGame()</tt> Returns the active game object.<br />
* <tt>StringVector getVFSSearchPaths</tt> 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.<br />
<br />
==== Game ====<br />
* <tt>string getKeyValue(string key)</tt> 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.<br />
<br />
=== GlobalRegistry ===<br />
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 <tt>user/scripts/aseExport/recentFilename</tt><br />
<br />
* <tt>string get(path)</tt> Returns the string value for the given path. Returns empty if nothing found.<br />
* <tt>set(path, value)</tt> Set the string value for the given path, overwriting any existing value.<br />
<br />
=== GlobalGrid ===<br />
The GlobalGrid object can be used to set the grid size of the current viewports.<br />
<br />
* <tt>int getGridPower()</tt> 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.<br />
* <tt>setGridSize(int gridsize)</tt> 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.<br />
* <tt>float getGridSize()</tt>Returns the currently active grid size in absolute units (e.g. 0.125 .. 256)<br />
* <tt>gridDown()</tt> Decreases the grid size (stops at 0.125)<br />
* <tt>gridUp()</tt> Increases the grid size (stops at 256)<br />
<br />
=== GlobalMap ===<br />
The GlobalMap object represents the currently loaded map. Its interface is quite thin at the moment:<br />
* <tt>SceneNode getWorldSpawn()</tt> 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.<br />
* <tt>string getMapName()</tt> Returns the name of the currently loaded map. This is "unnammed.map" for an unsaved map.<br />
<br />
=== Math Objects ===<br />
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.<br />
<br />
==== Vector2 ====<br />
A Vector2 is a two-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2)<br />
* <tt>float dot(Vector2 other)</tt> Returns the result of the inner product of this Vector2 with a second Vector2.<br />
* <tt>Vector2 crossProduct(Vector2 other)</tt> Returns the resulting vector of the cross product of this Vector2 with one another.<br />
<br />
==== Vector3 ====<br />
A Vector3 is a three-component floating point vector.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>float getLength()</tt> Returns the length of this vector.<br />
* <tt>float getLengthSquared()</tt> Returns the squared length (x^2 + y^2 + z^2)<br />
* <tt>float dot(Vector3 other)</tt> Returns the result of the inner product of this Vector3 with a second Vector3.<br />
* <tt>Vector3 crossProduct(Vector3 other)</tt> Returns the resulting vector of the cross product of this Vector3 with one another.<br />
* <tt>Vector3 getNormalised()</tt> Returns a normalised '''copy''' of this vector, leaves this vector untouched.<br />
* <tt>normalise()</tt> Normalises this vector. After this call, this vector is a unit vector.<br />
* <tt>Vector3 getInversed()</tt> Returns an inversed copy of this vector, with the components <1/x 1/y 1/z>.<br />
* <tt>float angle(Vector3 other)</tt> Returns the angle between this vector and the "other" Vector3.<br />
* <tt>bool isParallel(Vector3 other)</tt> Returns true (1) if this vector is parallel to the "other" vector.<br />
<br />
==== Vector4 / Quaternion ====<br />
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.<br />
* <tt>x</tt> Returns a reference to the first component x of this vector.<br />
* <tt>y</tt> Returns a reference to the second component y of this vector.<br />
* <tt>z</tt> Returns a reference to the third component z of this vector.<br />
* <tt>w</tt> Returns a reference to the fourth component w of this vector.<br />
* <tt>float dot(Vector4 other)</tt> Returns the result of the inner product of this Vector4 with a second Vector4.<br />
* <tt>Vector3 getProjected()</tt> Projects this Vector4 into three dimensional space, by dividing the first three components by w and returning the resulting Vector3.<br />
<br />
==== Vector Arithmetics ====<br />
All Vector objects support the most important operators, each compatible with a Vector of the same type.<br />
* +<br />
* -<br />
* +=<br />
* -=<br />
* < (lesser than, only supported by Vector2 and Vector3)<br />
<br />
==== AABB ====<br />
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.<br />
* <tt>AABB()</tt> Constructs an empty bounding box, which is invalid until its origin and extents are set to something valid.<br />
* <tt>AABB(Vector3 origin, Vector3 extents)</tt> Constructs a valid bounding box, using the given origin and extents.<br />
* <tt>Vector3 origin</tt> This property can be used to access the center Vector3 of this bounding box.<br />
* <tt>extents</tt> This property provides access to the symmetrical extents (the Vector3 pointing from the center to one corner)<br />
* <tt>bool isValid()</tt> Returns true (1) if this AABB is valid.<br />
* <tt>float getRadius()</tt> Returns the radius of this bounding box, i.e. the length of the "extents" vector.<br />
* <tt>includePoint(Vector3 other)</tt> Modifies this bounding box to include the given point, extending it when necessary.<br />
* <tt>includeAABB(AABB other)</tt> Modifies this bounding box to include the given AABB, extending it when necessary.<br />
<br />
=== GlobalRadiant ===<br />
The "Radiant" module plays a slightly different role for scripting than it does for the "internal" C++ code. Here, it provides some "convenience" methods.<br />
* <tt>EntityNode findEntityByClassname(string name)</tt> Returns the first matching entity with the given classname in the current scenegraph. Returns a NULL node if nothing is found.<br />
Example:<br />
worldspawn = Radiant.findEntityByClassname("worldspawn")<br />
worldspawn.setKeyValue('test', 'success')<br />
print('Worldspawn edited')<br />
<br />
=== GlobalSelectionSystem ===<br />
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.<br />
* <tt>SelectionInfo getSelectionInfo()</tt> 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.<br />
* <tt>foreachSelected(SelectionVisitor visitor)</tt> Visits the current selection using the given Visitor object (not counting components).<br />
* <tt>foreachSelectedComponent(SelectionVisitor visitor)</tt> Visits the current '''component''' selection using the given Visitor object.<br />
* <tt>setSelectedAll(bool selected)</tt> Sets the selection status of all objects in the scenegraph (not counting components like Vertices and Edges).<br />
* <tt>setSelectedAllComponents(bool selected)</tt> Sets the selection status of all components in the scenegraph (Vertices, Edges, Faces).<br />
* <tt>SceneNode ultimateSelected()</tt> Returns a reference to the last selected object. Will throw an exception if called with an empty selection, so check first using getSelectionInfo().<br />
* <tt>SceneNode penultimateSelected()</tt> 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().<br />
<br />
==== SelectionInfo ====<br />
This is the object returned by GlobalSelectionSystem.getSelectionInfo(). It provides just a few counters which can be used to inspect the currently selected object.<br />
* <tt>int totalCount</tt> The total number of selected objects, including components.<br />
* <tt>int patchCount</tt> The number of selected patches.<br />
* <tt>int brushCount</tt> The number of selected brushes.<br />
* <tt>int entityCount</tt> The number of selected entities.<br />
* <tt>int componentCount</tt> The number of selected components (Faces, Edges, Vertices).<br />
<br />
=== GlobalSelectionSetManager ===<br />
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.)<br />
* <tt>foreachSelectionSet(SelectionSetVisitor visitor)</tt> Traverses the available selection sets using the given visitor object. See install/scripts/test.py for an example.<br />
* <tt>SelectionSet createSelectionSet(string name)</tt> Creates a new selection set or overwrites the existing one with the given name.<br />
* <tt>deleteSelectionSet(string name)</tt> Deletes the named selection set.<br />
* <tt>deleteAllSelectionSets()</tt> Deletes ALL selection sets (irreversibly).<br />
* <tt>SelectionSet findSelectionSet(string name)</tt> Finds the selection set with the given name. Use the empty() method of the SelectionSet to check if the lookup succeeded.<br />
<br />
==== SelectionSet ====<br />
This is the object returned by GlobalSelectionSetManager .createSelectionSet() and GlobalSelectionSetManager .findSelectionSet(). (Since 1.4.0.)<br />
* <tt>string getName()</tt> Returns the name of this selection set.<br />
* <tt>bool empty()</tt> Returns TRUE if this selection set is empty.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>select()</tt> Selects all members/nodes of this selection set.<br />
* <tt>deselect()</tt> De-selects all members/nodes of this selection set.<br />
* <tt>assignFromCurrentScene()</tt> Clears this set and loads the currently selected nodes in the scene as new members into this set.<br />
<br />
=== GlobalSelectionGroupManager ===<br />
The GlobalSelectionGroupManager (not to be confused with the above Selection Set Manager) object provides routines for organising and manipulating groups. (since 2.4.0).<br />
* <tt>SelectionGroup createSelectionGroup()</tt> Creates a new selection group and returns it.<br />
* <tt>SelectionGroup getSelectionGroup(int id)</tt> Returns the selection group with the given ID.<br />
* <tt>SelectionGroup findOrCreateSelectionGroup(int id)</tt> Returns the selection group with the given ID. The group will be created if it doesn't exist yet.<br />
* <tt>setGroupSelected(int id, int selected)</tt> Selects or deselects all elements of the group with the given ID. Pass 1 to the <tt>selected</tt> argument to select items, 0 otherwise.<br />
* <tt>deleteAllSelectionGroups()</tt> Deletes ALL selection groups from the map. The actual elements are not removed, just the grouping information is removed.<br />
* <tt>deleteSelectionGroup(int id)</tt> Removes the selection group with the given ID. The actual elements are not removed, just the grouping information is removed.<br />
<br />
==== SelectionGroup ====<br />
This is the object returned by <tt>GlobalSelectionGroupManager.createSelectionGroup</tt>, <tt>GlobalSelectionGroupManager.findOrCreateSelectionGroup</tt> and <tt>GlobalSelectionGroupManager.getSelectionGroup</tt>. (Since 2.4.0.)<br />
* <tt>int getId()</tt> Returns the ID of this selection group.<br />
* <tt>string getName()</tt> Returns the name of this selection group.<br />
* <tt>setName(string name)</tt> Sets the name of this selection group.<br />
* <tt>addNode(SceneNode node)</tt> Adds a scene node to this group.<br />
* <tt>removeNode(SceneNode node)</tt> Removes a scene node from this group.<br />
* <tt>int size()</tt> Returns the number of elements in this group.<br />
* <tt>clear()</tt> Empties this selection set.<br />
* <tt>setSelected(int selected)</tt> Selects/deselects all members/nodes of this group (pass 1 to select, 0 to deselect).<br />
* <tt>foreachNode(SelectionGroupVisitor visitor)</tt> For every node in this group, call the <tt>visit</tt> method of the given visitor (see below).<br />
<br />
==== SelectionGroupVisitor ====<br />
Create an object deriving from this SelectionGroupVisitor and use it to visit every member of a selection group.<br />
* <tt>visit(SceneNode node)</tt> Required method which is called for every group member when using <tt>SelectionGroup.foreachNode()</tt><br />
<br />
''Example''<br />
import darkradiant as dr<br />
<br />
# List nodes in this group<br />
class SelectionGroupWalker(dr.SelectionGroupVisitor) :<br />
def visit(self, node):<br />
print('Group Member: ' + node.getNodeType())<br />
<br />
groupWalker = SelectionGroupWalker()<br />
group.foreachNode(groupWalker)<br />
<br />
=== GlobalMaterialManager ===<br />
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.<br />
<br />
* <tt>foreachMaterial(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* <tt>Material getMaterial(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
* <tt>bool materialExists(string name)</tt> Returns true if the named material is existing, false otherwise (since 2.12)<br />
* <tt>bool materialCanBeModified(string name)</tt> Returns true if the named material can be modified (is not defined in a PK4 files), false otherwise (since 2.12)<br />
* <tt>Material createEmptyMaterial(string name)</tt> Creates a new material using the given name. In case the name is already in use, a generated one will be assigned to the created material. (since 2.12)<br />
* <tt>Material copyMaterial(string nameOfOriginal, string nameOfCopy)</tt> Creates a copy of the given material and returns the reference to it. (since 2.12)<br />
* <tt>bool renameMaterial(string oldName, string newName)</tt> Renames the material named oldName to newName, and returns true if the operation was successful. If the new name is already in use, this returns false too. (since 2.12)<br />
* <tt>void removeMaterial(string name)</tt> Removes the named material. (since 2.12)<br />
* <tt>void saveMaterial(string name)</tt> Saves the named material to the file location as specified in its file info. If the path is not writable or the material is not suitable for saving, this will throw an exception. (since 2.12)<br />
* ''deprecated since 2.12'': <tt>foreachShader(MaterialVisitor visitor)</tt> Visit each known material with the given visitor object.<br />
* ''deprecated since 2.12'': <tt>Shader getMaterialForName(string name)</tt> Returns the material object for the given name. Returns a NULL object if nothing is found (isNull() will return true).<br />
<br />
==== MaterialVisitor ====<br />
A MaterialVisitor is needed for the GlobalMaterialManager.foreachMaterial() method to iterate over known materials. (Old name until 2.11 was: ShaderVisitor)<br />
* <tt>visit(Material s)</tt> Is invoked by the foreachMaterial() routine for each material, passing the object along.<br />
<br />
This example script will print all materials and the files they're defined in:<br />
import darkradiant as dr<br />
<br />
# This is the material visitor object we will use to traverse the materials<br />
class TestMaterialVisitor(dr.MaterialVisitor) :<br />
def visit(self, material):<br />
if not material.isNull():<br />
print('Found material: ' + material.getName() + ' defined in ' + material.getShaderFileName())<br />
<br />
materialvisitor = TestMaterialVisitor()<br />
GlobalMaterialManager.foreachMaterial(materialvisitor)<br />
<br />
==== Material ====<br />
The material object wraps around a known declaration, holding information about the shader stages and other things. (Old name until 2.11 was: Shader)<br />
* <tt>bool isNull()</tt> Returns true (1) if this a NULL material.<br />
* <tt>string getName()</tt> Returns the full name of this shader, e.g. "textures/darkmod/stone/brick/blocks_mixedsize01"<br />
* <tt>string getShaderFileName()</tt> Returns the filename this shader is defined in (e.g. "materials/tdm_stone_brick.mtr")<br />
* <tt>string getDescription()</tt> Returns the description string as parsed from the material.<br />
* <tt>bool isModified()</tt> Returns true (1) if this material has been modified (programmatically). (since 2.12)<br />
* <tt>string getDefinition()</tt> Returns the parsed (or generated) material definition source (the part between the two outermost curly braces).<br />
* <tt>bool isVisible()</tt> Returns true if this shader is visible, i.e. not currently filtered.<br />
* <tt>bool isAmbientLight()</tt> Returns true (1) if this is an ambient light material.<br />
* <tt>bool isBlendLight()</tt> Returns true (1) if this is a blend light material.<br />
* <tt>bool isFogLight()</tt> Returns true (1) if this is a fog light material.<br />
* <tt>bool isCubicLight()</tt> Returns true (1) if this is a cubic light material. (since 2.12)<br />
* <tt>string getEditorImageExpressionString()</tt> Returns the qer_editorImage part (since 2.12)<br />
* <tt>float getSortRequest()</tt> Returns the value of the "sort" keyword in this material (since 2.12)<br />
* <tt>float getPolygonOffset()</tt> Return a polygon offset if one is defined. The default is 0. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Get the desired texture repeat behaviour (since 2.12)<br />
* <tt>Material.CullType getCullType()</tt> Get the cull type (none, back, front) (since 2.12)<br />
* <tt>int getMaterialFlags()</tt> Get the combined bit flags that are set on this material (see Material.Flag below) (since 2.12)<br />
* <tt>int getSurfaceFlags()</tt> Get the combined bit surface flags that are set on this material (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>Material.SurfaceType getSurfaceType()</tt> Get the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>Material.DeformType getDeformType()</tt> Get the deform type (flare, sprite, ...) of this material (see Material.DeformType below) (since 2.12)<br />
* <tt>string getDeformExpressionString(int index)</tt> Returns the shader expression used to define the deform parameters (valid indices in [0..2]) (since 2.12)<br />
* <tt>string getDeformDeclName()</tt> Used for DeformType.PARTICLE/PARTICLE2; defines the name of the particle def (since 2.12)<br />
* <tt>int getSpectrum()</tt> Returns the spectrum of this shader, 0 is the default value (even without keyword in the material) (since 2.12)<br />
* <tt>Material.DecalInfo getDecalInfo()</tt> Returns the decal info structure of this material (since 2.12)<br />
* <tt>Material.Coverage getCoverage()</tt> The evaluated coverage of this material (see Material.Coverage below) (since 2.12)<br />
* <tt>string getLightFalloffExpressionString()</tt> Returns the map expression used to define the light falloff image (since 2.12)<br />
* <tt>MaterialStage.MapType getLightFalloffCubeMapType()</tt> Returns the map type of the light falloff image (cubeMap, map) (since 2.12)<br />
* <tt>string getGuiSurfArgument()</tt> The argument to the "guisurf" keyword, if not entity[2]3]. In case entity[2]3] is set, the corresponding surface flags are enabled (since 2.12)<br />
* <tt>string getRenderBumpArguments()</tt> Returns the argument string after the renderbump keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>string getRenderBumpFlatArguments()</tt> Returns the argument string after the renderbumpflat keyword, or an empty string if no statement is present (since 2.12)<br />
* <tt>(List of ScriptMaterialStage) getAllStages()</tt> Returns the list of all stages in this material (since 2.12)<br />
* <tt>int getNumStages()</tt> Return the number of stages in this material (since 2.12)<br />
* <tt>MaterialStage getStage(int index)</tt> Returns the stage with the given index (since 2.12)<br />
<br />
The following methods can only be called on materials that can be modified, otherwise an exception will be thrown. Check <tt>GlobalMaterialManager.materialCanBeModified()</tt> first.<br />
* <tt>revertModifications()</tt> Undo all changes to this material since it was last saved(since 2.12)<br />
* <tt>setShaderFileName(string fullPath)</tt> Set the mtr file name to define where this material should be saved to (since 2.12)<br />
* <tt>setDescription(string description)</tt> Set the material description (since 2.12)<br />
* <tt>setEditorImageExpressionFromString(string editorImagePath)</tt> Sets the qer_editorImage path of this material. (since 2.12)<br />
* <tt>setSortRequest(float/SortRequest value)</tt> Sets the sort request value of this material. See the predefined SortRequest values below (since 2.12)<br />
* <tt>resetSortRequest()</tt> Resets the sort request value of this material to its default. (since 2.12)<br />
* <tt>setPolygonOffset(float offset)</tt> Set the polygon offset of this material (since 2.12)<br />
* <tt>clearPolygonOffset()</tt> Removes the polygon offset from this material (since 2.12)<br />
* <tt>setClampType(Material.ClampType type)</tt> Set the desired texture repeat behaviour (see Material.ClampType below) (since 2.12)<br />
* <tt>setCullType(Material.CullType type)</tt> Set the cull type (see Material.CullType below) (since 2.12)<br />
* <tt>setMaterialFlag(Material.Flag flag)</tt> Set the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>clearMaterialFlag(Material.Flag flag)</tt> Clear the given material flag (see Material.Flag below) (since 2.12)<br />
* <tt>setSurfaceFlag(Material.SurfaceFlag flag)</tt> Set the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>clearSurfaceFlag(Material.SurfaceFlag flag)</tt> Clear the given surface flag (see Material.SurfaceFlag below) (since 2.12)<br />
* <tt>setSurfaceType(Material.SurfaceType type)</tt> Set the surface type (wood, flesh, etc.) of this material (see Material.SurfaceType below) (since 2.12)<br />
* <tt>setSpectrum(int spectrum)</tt> Sets the spectrum of this material (since 2.12)<br />
* <tt>setIsAmbientLight(int newValue)</tt> Pass true (1) to enable the ambient light flag on this material (since 2.12)<br />
* <tt>setIsBlendLight(int newValue)</tt> Pass true (1) to enable the blend light flag on this material (since 2.12)<br />
* <tt>setIsFogLight(int newValue)</tt> Pass true (1) to enable the fog light flag on this material (since 2.12)<br />
* <tt>setIsCubicLight(int newValue)</tt> Pass true (1) to enable the cubic light flag on this material (since 2.12)<br />
* <tt>setLightFalloffExpressionFromString(string expression)</tt> Set the light falloff map expression (since 2.12)<br />
* <tt>setLightFalloffCubeMapType(MaterialStage.MapType type)</tt> Set the map type of the light falloff image (since 2.12)<br />
* <tt>int addStage(MaterialStage.Type type)</tt> Create a new stage with the given type, returns the index of the new stage (since 2.12)<br />
* <tt>removeStage(int index)</tt> Removes the stage with the new index (since 2.12)<br />
* <tt>int duplicateStage(int index)</tt> Duplicates the stage with the given index, returns the index of the new stage (since 2.12)<br />
* <tt>swapStagePosition(int first, int second)</tt> Swaps the position of the two given stages. (since 2.12)<br />
<br />
==== Material.SurfaceType ====<br />
* Material.SurfaceType.'''DEFAULT'''<br />
* Material.SurfaceType.'''METAL'''<br />
* Material.SurfaceType.'''STONE'''<br />
* Material.SurfaceType.'''FLESH'''<br />
* Material.SurfaceType.'''WOOD'''<br />
* Material.SurfaceType.'''CARDBOARD'''<br />
* Material.SurfaceType.'''LIQUID'''<br />
* Material.SurfaceType.'''GLASS'''<br />
* Material.SurfaceType.'''PLASTIC'''<br />
* Material.SurfaceType.'''RICOCHET'''<br />
* Material.SurfaceType.'''AASOBSTACLE'''<br />
* Material.SurfaceType.'''SURFTYPE10'''<br />
* Material.SurfaceType.'''SURFTYPE11'''<br />
* Material.SurfaceType.'''SURFTYPE12'''<br />
* Material.SurfaceType.'''SURFTYPE13'''<br />
* Material.SurfaceType.'''SURFTYPE14'''<br />
* Material.SurfaceType.'''SURFTYPE15'''<br />
<br />
==== Material.Flag ====<br />
These are bit flags that can be set/cleared/combined on a material.<br />
* Material.Flag.'''NOSHADOWS'''<br />
* Material.Flag.'''NOSELFSHADOW'''<br />
* Material.Flag.'''FORCESHADOWS'''<br />
* Material.Flag.'''NOOVERLAYS'''<br />
* Material.Flag.'''FORCEOVERLAYS'''<br />
* Material.Flag.'''TRANSLUCENT'''<br />
* Material.Flag.'''FORCEOPAQUE'''<br />
* Material.Flag.'''NOFOG'''<br />
* Material.Flag.'''NOPORTALFOG'''<br />
* Material.Flag.'''UNSMOOTHEDTANGENTS'''<br />
* Material.Flag.'''MIRROR'''<br />
* Material.Flag.'''POLYGONOFFSET'''<br />
* Material.Flag.'''ISLIGHTGEMSURF'''<br />
<br />
==== Material.SurfaceFlag ====<br />
Various flags that can be set/cleared/combined on a material<br />
* Material.SurfaceFlag.'''SOLID'''<br />
* Material.SurfaceFlag.'''OPAQUE'''<br />
* Material.SurfaceFlag.'''WATER'''<br />
* Material.SurfaceFlag.'''PLAYERCLIP'''<br />
* Material.SurfaceFlag.'''MONSTERCLIP'''<br />
* Material.SurfaceFlag.'''MOVEABLECLIP'''<br />
* Material.SurfaceFlag.'''IKCLIP'''<br />
* Material.SurfaceFlag.'''BLOOD'''<br />
* Material.SurfaceFlag.'''TRIGGER'''<br />
* Material.SurfaceFlag.'''AASSOLID'''<br />
* Material.SurfaceFlag.'''AASOBSTACLE'''<br />
* Material.SurfaceFlag.'''FLASHLIGHT_TRIGGER'''<br />
* Material.SurfaceFlag.'''NONSOLID'''<br />
* Material.SurfaceFlag.'''NULLNORMAL'''<br />
* Material.SurfaceFlag.'''AREAPORTAL'''<br />
* Material.SurfaceFlag.'''NOCARVE'''<br />
* Material.SurfaceFlag.'''DISCRETE'''<br />
* Material.SurfaceFlag.'''NOFRAGMENT'''<br />
* Material.SurfaceFlag.'''SLICK'''<br />
* Material.SurfaceFlag.'''COLLISION'''<br />
* Material.SurfaceFlag.'''NOIMPACT'''<br />
* Material.SurfaceFlag.'''NODAMAGE'''<br />
* Material.SurfaceFlag.'''LADDER'''<br />
* Material.SurfaceFlag.'''NOSTEPS'''<br />
* Material.SurfaceFlag.'''GUISURF'''<br />
* Material.SurfaceFlag.'''ENTITYGUI'''<br />
* Material.SurfaceFlag.'''ENTITYGUI2'''<br />
* Material.SurfaceFlag.'''ENTITYGUI3'''<br />
<br />
==== Material.SortRequest ====<br />
Pre-defined sort request constants as corresponding to the TDM engine code:<br />
* Material.SortRequest.'''SUBVIEW'''<br />
* Material.SortRequest.'''GUI'''<br />
* Material.SortRequest.'''BAD'''<br />
* Material.SortRequest.'''OPAQUE'''<br />
* Material.SortRequest.'''PORTAL_SKY'''<br />
* Material.SortRequest.'''DECAL'''<br />
* Material.SortRequest.'''FAR'''<br />
* Material.SortRequest.'''MEDIUM'''<br />
* Material.SortRequest.'''CLOSE'''<br />
* Material.SortRequest.'''ALMOST_NEAREST'''<br />
* Material.SortRequest.'''NEAREST'''<br />
* Material.SortRequest.'''AFTER_FOG'''<br />
* Material.SortRequest.'''POST_PROCESS'''<br />
<br />
==== Material.ClampType ====<br />
* Material.ClampType.'''REPEAT''' default = no clamping<br />
* Material.ClampType.'''NOREPEAT''' "clamp"<br />
* Material.ClampType.'''ZEROCLAMP''' zeroclamp"<br />
* Material.ClampType.'''ALPHAZEROCLAMP''' "alphazeroclamp"<br />
<br />
==== Material.CullType ====<br />
* Material.CullType.'''BACK''' (default)<br />
* Material.CullType.'''FRONT''' (backsided)<br />
* Material.CullType.'''NONE''' (twosided)<br />
<br />
==== Material.DeformType ====<br />
* Material.DeformType.'''NONE'''<br />
* Material.DeformType.'''SPRITE'''<br />
* Material.DeformType.'''TUBE'''<br />
* Material.DeformType.'''FLARE'''<br />
* Material.DeformType.'''EXPAND'''<br />
* Material.DeformType.'''MOVE'''<br />
* Material.DeformType.'''TURBULENT'''<br />
* Material.DeformType.'''EYEBALL'''<br />
* Material.DeformType.'''PARTICLE'''<br />
* Material.DeformType.'''PARTICLE2'''<br />
<br />
==== Material.DecalInfo ====<br />
* <tt>int stayMilliSeconds</tt><br />
* <tt>int fadeMilliSeconds</tt><br />
* <tt>Vector4 startColour</tt><br />
* <tt>Vector4 endColour</tt><br />
<br />
==== Material.Coverage ====<br />
* Material.Coverage.'''UNDETERMINED'''<br />
* Material.Coverage.'''OPAQUE''' <br />
* Material.Coverage.'''PERFORATED''' <br />
* Material.Coverage.'''TRANSLUCENT'''<br />
<br />
=== MaterialStage ===<br />
Note: There are two material stage interfaces, this one covers the read-only methods. If you intend to modify a stage, be sure to use the <tt>EditableMaterialStage</tt> type, which can be acquired through <tt>Material.getEditableStage</tt><br />
* <tt>MaterialStage.Type getType()</tt> Returns the blend type of this stage (diffuse, specular, blend) (since 2.12)<br />
* <tt>int getStageFlags()</tt> Returns the combined stage flags value (see MaterialStage.Flag below) (since 2.12)<br />
* <tt>pair getBlendFuncStrings()</tt> Get the blend strings as defined in the material def, e.g. "add" or "gl_one, gl_zero". Returns a tuple of size 2. (since 2.12)<br />
* <tt>Material.ClampType getClampType()</tt> Each stage can have its own clamp type, overriding the per-material one (since 2.12)<br />
* <tt>MaterialStage.TexGenType getTexGenType()</tt> Returns the texgen type: normal, reflect, skybox, etc., use getTexGenParam(i) to retrieve the wobblesky parameters [0..2] (see MaterialStage.TexGenType below) (since 2.12)<br />
* <tt>string getTexGenExpressionString(int index)</tt> TexGen type wobblesky has 3 parameters, get the expressions used to calculate them here. Index in [0..2] (since 2.12)<br />
* <tt>string getColourExpressionString(MaterialStage.ColourComponent selector)</tt> Returns the expression to calculate the R/G/B/A vertex colour values. The selectors RGB and RGBA will only return a non-empty string if all the expressions are actually the same.(since 2.12)<br />
* <tt>MaterialStage.VertexColourMode getVertexColourMode()</tt> Returns the vertex colour mode, if specified (see MaterialStage.VertexColourMode below) (since 2.12)<br />
* <tt>MaterialStage.MapType getMapType()</tt> Get the map type used by this stage (see MaterialStage.MapType below) (since 2.12)<br />
* <tt>List(MaterialStage.Transformation) getTransformations() The list of transformations defined in this stage, in the order they appear in the declaration (since 2.12)</tt><br />
* <tt>Vector2 getRenderMapSize()</tt> Returns the dimensions specifying the map size for stages using the "mirrorRenderMap", "remoteRenderMap" keywords. (since 2.12)<br />
* <tt>string getAlphaTestExpressionString()</tt> Get the alpha test expression of this stage (since 2.12)<br />
* <tt>string getConditionExpressionString()</tt> Get the condition expression of this stage (since 2.12)<br />
* <tt>string getVertexProgram()</tt> Returns the name of this stage's vertex program (since 2.12)<br />
* <tt>string getFragmentProgram()</tt> Returns the name of this stage's fragment program (since 2.12)<br />
* <tt>int getNumVertexParms()</tt> The number of defined vertex parameters (since 2.12)<br />
* <tt>int getNumFragmentMaps()</tt> Returns the number of fragment maps in this stage (since 2.12)<br />
* <tt>MaterialStage.VertexParm getVertexParm(int index)</tt> Returns the indexed vertex parm used in this stage (since 2.12)<br />
* <tt>MaterialStage.FragmentMap getFragmentMap(int index)</tt> Returns the indexed fragment map used in this stage (since 2.12)<br />
<br />
==== MaterialStage.Type ====<br />
* MaterialStage.Type.'''DIFFUSE'''<br />
* MaterialStage.Type.'''BUMP'''<br />
* MaterialStage.Type.'''SPECULAR'''<br />
* MaterialStage.Type.'''BLEND'''<br />
<br />
==== MaterialStage.MapType ====<br />
* MaterialStage.MapType.'''MAP'''<br />
* MaterialStage.MapType.'''CUBEMAP'''<br />
* MaterialStage.MapType.'''CAMERACUBEMAP'''<br />
* MaterialStage.MapType.'''VIDEOMAP'''<br />
* MaterialStage.MapType.'''SOUNDMAP'''<br />
* MaterialStage.MapType.'''MIRRORRENDERMAP'''<br />
* MaterialStage.MapType.'''REMOTERENDERMAP'''<br />
<br />
==== MaterialStage.Flag ====<br />
* MaterialStage.Flag.'''IGNORE_ALPHATEST'''<br />
* MaterialStage.Flag.'''FILTER_NEAREST'''<br />
* MaterialStage.Flag.'''FILTER_LINEAR'''<br />
* MaterialStage.Flag.'''HIGHQUALITY'''<br />
* MaterialStage.Flag.'''FORCE_HIGHQUALITY'''<br />
* MaterialStage.Flag.'''NO_PICMIP'''<br />
* MaterialStage.Flag.'''MASK_RED'''<br />
* MaterialStage.Flag.'''MASK_GREEN'''<br />
* MaterialStage.Flag.'''MASK_BLUE'''<br />
* MaterialStage.Flag.'''MASK_ALPHA'''<br />
* MaterialStage.Flag.'''MASK_DEPTH'''<br />
* MaterialStage.Flag.'''IGNORE_DEPTH'''<br />
<br />
==== MaterialStage.TexGenType ====<br />
* MaterialStage.TexGenType.'''NORMAL'''<br />
* MaterialStage.TexGenType.'''REFLECT'''<br />
* MaterialStage.TexGenType.'''SCREEN'''<br />
* MaterialStage.TexGenType.'''SKYBOX'''<br />
* MaterialStage.TexGenType.'''WOBBLESKY'''<br />
<br />
==== MaterialStage.ColourComponent ====<br />
* MaterialStage.ColourComponent.'''RED'''<br />
* MaterialStage.ColourComponent.'''GREEN'''<br />
* MaterialStage.ColourComponent.'''BLUE'''<br />
* MaterialStage.ColourComponent.'''ALPHA'''<br />
* MaterialStage.ColourComponent.'''RGB'''<br />
* MaterialStage.ColourComponent.'''RGBA'''<br />
<br />
==== MaterialStage.VertexColourMode ====<br />
* MaterialStage.VertexColourMode.'''NONE'''<br />
* MaterialStage.VertexColourMode.'''MULTIPLY'''<br />
* MaterialStage.VertexColourMode.'''INVERSE_MULTIPLY'''<br />
<br />
==== MaterialStage.TransformType ====<br />
* MaterialStage.TransformType.'''TRANSLATE'''<br />
* MaterialStage.TransformType.'''SCALE'''<br />
* MaterialStage.TransformType.'''ROTATE'''<br />
* MaterialStage.TransformType.'''CENTERSCALE'''<br />
* MaterialStage.TransformType.'''SHEAR'''<br />
<br />
==== MaterialStage.Transformation ====<br />
* <tt>MaterialStage.TransformType type</tt> The type of this transformation<br />
* <tt>string expression1</tt> The first expression string<br />
* <tt>string expression2</tt> The second expression string (always empty for TransformType.Rotate)<br />
<br />
==== MaterialStage.VertexParm ====<br />
* <tt>int index</tt> The index of this vertex parameter<br />
* <tt>List(string) expression</tt> The list of expressions defining this parameter's values (max. 4)<br />
<br />
==== MaterialStage.FragmentMap ====<br />
* <tt>int index</tt> The index of this fragment map<br />
* <tt>List(string) options</tt> The list of options passed to this map<br />
* <tt>string mapExpression</tt> The map expression used in this fragment map<br />
<br />
=== GlobalDialogManager ===<br />
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:<br />
* <tt>Dialog createDialog(string title)</tt> Creates and returns a new Dialog object with the given window title.<br />
* <tt>Dialog createMessageBox(string title, string text, MessageType type)</tt> 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.<br />
<br />
==== Dialog ====<br />
Once you've created a new Dialog object, it offers the following functions:<br />
* <tt>setTitle(string title)</tt>: 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.<br />
* <tt>Dialog.Result run()</tt> Displays the dialogs and waits until the user hits any button.<br />
* <tt>Handle addLabel(string labelText)</tt> Adds a label with the given text.<br />
* <tt>Handle addComboBox(string label, StringVector options)</tt> Adds a combo (dropdown) box with the given options (see below for an example about how to do that).<br />
* <tt>Handle addEntryBox(string label)</tt> Adds a text entry box.<br />
* <tt>Handle addPathEntry(string label, bool foldersOnly)</tt> Adds a file/folder browse field. When foldersOnly is true (1) the file browser only accepts paths as input.<br />
* <tt>Handle addSpinButton(string label, float min, float max, float step, int digits)</tt> 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+).<br />
* <tt>Handle addCheckbox(string label)</tt> Adds a simple checkbox (can be ticked on or off).<br />
* <tt>string getElementValue(Handle handle)</tt> 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.<br />
* <tt>setElementValue(Handle handle, string value)</tt>. 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.<br />
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.<br />
<br />
When the dialog is first created it consists of a title and an OK and CANCEL button only. You'll want to call the <tt>add*()</tt> 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 <tt>dialog.addLabel()</tt> followed by <tt>dialog.addEntryBox()</tt> 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.<br />
<br />
==== MessageType ====<br />
* '''Dialog.CONFIRM''': The message carries a "Notification" icon (e.g. a light bulb) and features a single OK button.<br />
* '''Dialog.ASK''': The message is decorated with a "question" image and offers the buttons YES and NO.<br />
* '''Dialog.WARNING''': The message has a warning sign on it and has a simple OK button.<br />
* '''Dialog.ERROR''': The message has an error image (a "stop" sign) on it and has a simple OK button.<br />
* '''Dialog.YESNOCANCEL''': The message carries three buttons: Yes, No and Cancel. Like the one used for DarkRadiant's overwrite map confirmation dialog.<br />
<br />
==== Result ====<br />
When a dialog is finished running, the result is returned by the run() method. It can be one of several:<br />
* '''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).<br />
* '''Dialog.OK''': The user clicked the OK button.<br />
* '''Dialog.NO''': The user clicked the NO button.<br />
* '''Dialog.YES''': The user clicked the YES button. <br />
<br />
==== Examples ====<br />
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:<br />
import darkradiant as dr<br />
<br />
dialog = GlobalDialogManager.createMessageBox("Confirmation Box", "Confirm <b>this</b>", dr.Dialog.CONFIRM)<br />
dialog.run()<br />
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 <b>this</b>" 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.<br />
<br />
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:<br />
import darkradiant as dr<br />
<br />
# Test creating a new dialog<br />
dialog = GlobalDialogManager.createDialog("Test")<br />
<br />
# Add a label<br />
dialog.addLabel("Testlabel")<br />
<br />
# Add an entry box and remember the handle<br />
entryHandle = dialog.addEntryBox("Entry")<br />
<br />
# Add a spin button<br />
dialog.addSpinButton("Spinner", 0, 10, 0.5)<br />
<br />
# Add a combo box, the options must be passed in the form of a StringVector<br />
options = StringVector()<br />
options.append("Test1")<br />
options.append("Test2")<br />
dialog.addComboBox("Test", options)<br />
<br />
# Add a simple checkbox<br />
dialog.addCheckbox("TestCheckbox")<br />
<br />
if dialog.run() == dr.Dialog.OK:<br />
print("User clicked OK.")<br />
<br />
=== GlobalSoundManager ===<br />
The sound manager provides an interface to the sound shader declarations, plus simple playback/stop routines.<br />
<br />
* <tt>SoundShader getSoundShader(string shaderName)</tt> Looks up the sound shader by name.<br />
* <tt>bool playSound(string fileName)</tt> Tries to playback the sound file given by its VFS path. Returns 1 if the sound file could be located, 0 otherwise.<br />
* <tt>stopSound()</tt> Stops the currently played sound.<br />
<br />
==== SoundShader ====<br />
This is the object returned by GlobalSoundManager.getSoundShader(). It resembles a single sound shader declaration in the .sndshd files.<br />
* <tt>bool isNull()</tt> 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)<br />
* <tt>string getName()</tt> The name of this sound shader<br />
* <tt>SoundRadii getRadii()</tt> The Radii object containing min/max values.<br />
* <tt>StringVector getSoundFileList()</tt> Returns the list of sound files used in this shader (by their VFS path).<br />
* <tt>string getShaderFilePath()</tt> Returns the mod-relative path to the .sndshd file this shader has been defined in (since 2.8.1).<br />
* <tt>string getDefinition()</tt> Returns the source text of the sound shader declaration (only the inner part within the curly braces) (since 2.8.1).<br />
<br />
==== SoundRadii ====<br />
This is the object returned by SoundShader.getRadii(). <br />
* <tt>float getMin(bool inMetres)</tt> Gets the minimum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMin(float min, bool inMetres)</tt> Set the minimum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
* <tt>float getMax(bool inMetres)</tt> Gets the maximum radius of this sound shader. The flag indicates whether the value should be returned in units or meters.<br />
* <tt>setMax(float max, bool inMetres)</tt> Set the maximum radius of this sound shader. The flag indicates whether the value is provided in units or meters.<br />
<br />
==== Example Code ====<br />
soundshader = GlobalSoundManager.getSoundShader('tdm_ai_lady_alertdown_to_idle')<br />
<br />
if not soundshader.isNull():<br />
print('Name of this sound shader: ' + soundshader.getName())<br />
<br />
radii = soundshader.getRadii()<br />
<br />
print('Minimum radius in meters: ' + str(radii.getMin(1)))<br />
print('Maximum radius in meters: ' + str(radii.getMax(1)))<br />
<br />
fileList = soundshader.getSoundFileList()<br />
for i in range(0, len(fileList)):<br />
print(' Sound file used by this shader: ' + fileList[i])<br />
<br />
if (len(fileList) > 0):<br />
GlobalSoundManager.playSound(fileList[0])<br />
<br />
=== GlobalCameraManager ===<br />
The camera manager provides an interface to the active camera view of DR. Use it to query or set the active camera's position and angles, among a few other settings.<br />
<br />
* <tt>CameraView getActiveView()</tt> Returns the active camera (since 2.8.1)<br />
<br />
==== CameraView ====<br />
This is the object returned by GlobalCameraManager.getActiveView(). It resembles the camera view used to render the 3D view. This whole interface can be found in DR 2.8.1 or higher.<br />
<br />
* <tt>Vector3 getCameraOrigin()</tt> Returns the current 3D position of the camera.<br />
* <tt>setCameraOrigin(Vector3 newOrigin)</tt> Sets the new camera position.<br />
* <tt>Vector3 getCameraAngles()</tt> Returns the camera's orientation as Euler angles (pitch, yaw, roll) in degrees.<br />
* <tt>setCameraAngles(Vector3 newAngles)</tt> Sets the new camera orientation (pitch, yaw, roll) in degrees.<br />
* <tt>setOriginAndAngles(Vector3 newOrigin, Vector3 newAngles)</tt> Sets the new camera position and orientation (pitch, yaw, roll) in degrees.<br />
* <tt>Vector3 getRightVector()</tt> Returns the direction pointing towards the right of the camera's view direction<br />
* <tt>Vector3 getUpVector()</tt> Returns the direction pointing upwards of the camera's view direction<br />
* <tt>float getFarClipPlaneDistance()</tt> Returns the distance of the camera's cubic clip plane<br />
* <tt>setFarClipPlaneDistance(float newDistance)</tt> Sets the distance of the camera's cubic clip plane<br />
<br />
==== Example Code ====<br />
import darkradiant as dr<br />
<br />
camview = GlobalCameraManager.getActiveView()<br />
print(camview.getCameraOrigin())<br />
camview.setCameraOrigin(dr.Vector3(50,0,50))<br />
<br />
[[Category:DarkRadiant]]</div>Greebo