Q3Radiant plugin SDK
Version: Q3Radiant
build 201
Last updated: 06/24/2000
What do I have?
PluginHeaders/*: all headers needed to build
Radiant plugins
SampleDll/*: an empty plugin nutshell
Q3Plugin/*: TexTool plugin source code
Plugin basics:
main features available to plugins:
-
Manipulate MAP data: read and write brushes, epairs and entities
(patches not supported yet)
-
Override the BSP menu to process your own building commands
-
Read / Write project settings epairs
-
Use OpenGL to draw in the 2D/3D view, or in your own plugin
windows
-
Use listeners to catch events in Radiant (like a change of
texture or brush select / deselect)
-
Use listeners to listen for window events (for mouse interaction
in the 2D view)
-
Create new plugin entities that show up in the Radiant window,
which you can draw yourself and handle the user interaction
-
Use the Radiant internal parser to hook your own MAP format
changes for plugin entities
-
Access polygon and texture information on the current selected
face
-
Override the texture / shader code to provide your own texture
formats and shader system
-
Add new surface properties, and change the MAP format accordingly
overall structure of a plugin:
A plugin is a DLL (dynamic loading library) that exposes
some API to Radiant. Plugins must be put in the plugins/ directory, they
get loaded at startup by Radiant. Any plugin has a few required entry points
in order to get loaded correctly:
-
QERPlug_Init is the first entry point called, used
for initialization and sending back the plugin name that appears in the
console
-
QERPlug_GetName returns the name of the plugin as
it appears in the plugin menu
-
QERPlug_GetCommandList returns a list describing
the items in the plugin submenu
-
QERPlug_GetFuncTable returns the address of the
_QERFuncTable_1 of the plugin. After Radiant got the pointer to the function
table it will fill it and the plugin is able to call into the editor.
-
QERPlug_Dispatch is called when the user hits a
command in the plugin menu. The plugin is then free to process.
the function table and interfaces:
Instead of exporting entry points, Radiant fills in function
pointer tables. The main and required function table is _QERFuncTable_1.
Each plugin must have it and let Radiant fill it. Some additional or specialized
functionalities can be accessed with other tables like _QERQglTable
for GL stuff. These have to be requested to Radiant using _QERFuncTable_1::m_pfnRequestInterface
(see TexTool for an example). Each additional function table has
a "globally unique identifier" (QERQglTable_GUID for GL stuff)
that's used to identify the interface across plugins.
NOTE: some function tables are used by Radiant and must
be filled by the plugin (ie. they work in reverse compared to usual ones).
In this case the plugin must export an additional entry point int WINAPI
QERPlug_RequestInterface( REFGUID, LPVOID );
virtual classes:
some stuff is better represented by an abstract C++ class.
For those with COM knowledge, it's just a very lightweight COM way of doing
things. These classes have very basic reference counting through IncRef()
and DecRef() .. you are supposed to increment or decrement the
reference count each time you store or release a pointer to these classes,
otherwise they could get unexpectedly erased and you would be very very
sorry. The IListener class in IMessaging.h can be implemented
by the plugin and handed over to Radiant to listen for events. See TexTool
for examples.
More stuff:
If you need more information or if you want new features
for plugins, see the source code for TexTool and Curry.
TexTool
source comes with the plugin SDK, and Curry source is available
from
their web site. You can browse
it online from the
project page. PrtView
has neat code samples on how to draw in the 2D views or camera window.
These two plugins are under GPL licensing. The dedicated place to talk
about plugin coding is the plugins-coding
mailing list ... see you there. You may also get an updated list of
the plugins for Radiant on our dedicated
web site.
Conclusion:
this document is intended as a quickstart for potential
plugin writers. I hope it meets it's objective. It's not a complete and
systematic documentation, I doubt there will be one ever unless someone
decides to do it. Feel free to send me contributions to this document.
Send feedback to me.