Common Elements
This page discusses the components that are common to all plug-ins. These
are the structural components that form the bridge between LightWave and
your plug-ins. They have funny names and do possibly unfamiliar things,
so we need to introduce some terminology.
The host is the program, Layout or Modeler, for example, that
runs your plug-ins.
A plug-in module is a file, usually with a .p extension,
that contains one or more LightWave plug-ins. Any number of plug-ins can
be compiled together into a single module. It's common for an image loader
and an image saver to be together in the same file, for example.
Every plug-in file needs a server description that lists the
plug-ins in the file, and every plug-in needs a special entry point function,
its activation function. Both of these are defined in the lwserver.h
header file. Each plug-in file also contains initialization and cleanup
functions called Startup and Shutdown.
Server Description
The server description lists what your plug-in file contains. It's the
first thing the host examines when it loads your module. The list appears
in your source code as an array of ServerRecords.
typedef struct st_ServerRecord {
const char *className;
const char *name;
ActivateFunc *activate;
ServerTagInfo *tagInfo;
} ServerRecord;
-
className
-
A string containing the class of the plug-in. The class identifies what
kind of plug-in this is. The header files for classes contain #defines
for each class name. These are also listed in the documentation
for each class.
-
name
-
A string containing the name by which LightWave will uniquely identify
your plug-in. This is the name LightWave uses internally and saves in scene
and object files. It's also the name displayed to the user if the plug-in
doesn't supply at least one user name. The name must be a string of ASCII
characters in the range 33 to 127 (note that this excludes spaces). Case
is significant.
Although this allows punctuation and other special characters to
appear in the name, you're strongly encouraged to limit names to those
that would be legal identifiers in the C language. C identifiers contain
letters, numbers and the underscore character (ASCII 0x5F). Image saver
names, which by convention end with the default filename extension in parentheses,
are an exception to this rule.
The use of non-alphanumeric initial characters to force your plug-ins
to appear first, or together, in lexicographically sorted lists is discouraged.
This practice may interfere with LightWave's internal name processing and
may conflict with conventions that evolve in the future.
Each class has its own name space, so plug-ins of different classes
can have the same name. Although you'll probably want to avoid giving unrelated
plug-ins the same name, you must use the same name for the interface
class associated with a handler. This is how
the host matches a handler with its interface.
-
activate
-
The activation function. See below.
-
tagInfo
-
An array of tag strings that describe the plug-in. Among other things,
this is where you list the name that will be displayed to your users in
LightWave's interface.
Server Tags
The ServerRecord's tagInfo field is an array of ServerTagInfo
structures.
typedef struct st_ServerTagInfo {
const char *string;
unsigned int tag;
} ServerTagInfo;
Each tag contains two codes combined using bitwise-or. The high word is
the tag type, and the low word is the language ID. Not all of the tags
are supported yet. Currently defined tag types include the following.
-
SRVTAG_USERNAME
-
The name displayed to the user in LightWave's interface. Multiple user
names for different locales can be provided
by combining this type code with different language IDs. LightWave attempts
to select the name that's most appropriate for the locale of the user's
machine. Unlike the internal server name, there are no restrictions on
what the string may contain.
Japanese strings should be encoded as JIS on Windows and EUC on Unix.
-
SRVTAG_BUTTONNAME
-
The string that will appear on a button or in a popup list used to invoke
your plug-in. This is usually an abbreviated version of your user name.
-
SRVTAG_CMDGROUP
-
The LightWave interface organizes commands, including plug-ins, into command
groups. The command group you specifiy determines the heading under which
users will find your plug-in on menu and key customization dialogs. The
command group can be a predefined group, or a new group created simply
by listing its name.
SRVTAG_SELECTCMD
-
The string in this tag will be executed as a command when an item with
this plug-in applied is selected in Layout. This is useful for activating
special tools for certain custom objects, among other things.
In general, the predefined group names are lowercase versions of
the group names displayed in the interface. When using one of these groups,
the language ID should be 0. Predefined group names are automatically translated
to the locale of the user's machine. The following is a partial list of
the predefined command groups.
Both |
Layout |
Modeler |
display
file
preferences
windows
selection
additional |
bones
cameras
effects
items
lights
motion
objects
previews
rendering
time |
create
construct
edit
mappings
modify
polygons
texture |
-
SRVTAG_MENU
-
For plug-ins that can be activated as commands or tools (all Modeler classes,
plus generics in Layout), the menu string specifies the location of the
plug-in's node in LightWave's menu system. Like command groups, the menu
string can refer to predefined or custom nodes. They can also specify a
"path" resembling a filename, with optional root menu nodes followed by
a colon and other nodes separated by forward slashes, and the nodes can
be a mix of predefined and custom. The path
"tools/objects/Quadrics"
for example, would create a (custom) "Quadrics" popup on the (predefined)
"Tools" tab, while
"polygon/Metaballs"
would create a "Metaballs" group. In general, the menu tag path has the
form
"[menu:]tab[/group[/group...]]"
and the menu info tag can contain many of these strings separated by commas.
The string
"multiply/replicate,LMB:Ultra Studio"
would place the command or tool into the standard location in the main
menu and into a custom group in the left mouse button popup. It's even
possible to place commands into the bottom command bar in Modeler, but
this isn't recommended, since the screen real estate there is limited.
The predefined menu hierarchy hadn't been finalized at the time this
document was last updated.
-
SRVTAG_DESCRIPTION
-
A line of text describing the plug-in. This might be displayed in the interface
as hint text or as a description next to the user name in customization
dialogs.
-
SRVTAG_ENABLE
-
A string defining the conditions under which the plug-in should be active.
This is currently used for Modeler tools and commands to determine the
enable state of the plug-in's button. Possible values include
"pnt" - active points
"pol" - active polygons
"spnt" - directly selected points
"spol" - directly selected polygons
Compound conditions, which would combine these into boolean expressions,
aren't supported yet but may be in the future.
The language ID is a code indicating the language for the name string.
The language IDs are identical to those defined in the Microsoft Win32
API and exposed in the Microsoft Visual C++ winnt.h header file.
Bits 7 - 0 define the language group and bits 15 - 8 define the sublanguage.
lwserver.h contains symbols for some
of the more common language IDs.
0x0407 LANGID_GERMAN
0x0409 LANGID_USENGLISH
0x0809 LANGID_UKENGLISH
0x040a LANGID_SPANISH
0x040c LANGID_FRENCH
0x0410 LANGID_ITALIAN
0x0411 LANGID_JAPANESE
0x0412 LANGID_KOREAN
0x0419 LANGID_RUSSIAN
0x041D LANGID_SWEDISH
Activation Function
The activation function is the entry point for the service provided
by your plug-in. For some plug-in classes, this may be the only function
the host calls in your plug-in (other than the startup and shutdown functions).
For others, the activation function is where the host finds out about the
plug-in's callback functions.
XCALL_( int )
MyActivate( long version, GlobalFunc *global, void *local,
void *serverData );
-
version
-
A class-specific version number. As development of LightWave continues,
the interaction between the host and a given plug-in class is sometimes
redefined. This number tells you, among other things, what version of the
local data the host has passed. See the compatibility discussion for more
information on using this value. In most cases, though, you'll test this
value against the version number defined in the header file for your plug-in's
class and return AFUNC_BADVERSION if they don't match.
-
global
-
A function that gives your plug-in access to services provided by the host
and by Global class plug-ins. See the pages about the global
function and Global plug-ins for more information.
-
local
-
Class-specific data. Each plug-in class receives different data through
this argument. The documentation for each class, in fact, is primarily
concerned with describing the class's local argument. For handler classes,
this points to a structure that the plug-in needs to fill. The host gets
pointers to other functions in your plug-in this way.
-
serverData
-
The data pointer returned by the startup function. Unless you replaced
the default startup function, you should ignore this argument. In particular,
don't try to dereference the pointer, since on most systems it contains
an invalid (although non-NULL) address.
The activation function returns a code that
tells the host whether the plug-in was activated successfully.
-
AFUNC_BADVERSION
-
The version argument differs from what your plug-in supports. In some cases
the host will try again with a lower version number.
-
AFUNC_BADGLOBAL
-
A call to the global function failed.
-
AFUNC_BADLOCAL
-
Your plug-in doesn't like something in the local data.
-
AFUNC_BADAPP
-
The host is a program you don't support.
-
AFUNC_OK
-
Return this when none of the other values is appropriate.
Startup and Shutdown
These two optional entry points allow the module to initialize itself
when it is first loaded and to clean itself up before being unloaded.
void *Startup( void );
void Shutdown( void *serverData );
Most plug-in files don't require module-level initialization and cleanup.
They use the empty startup and shutdown functions supplied by the SDK linker
library.
The startup function is called when the plug-in is first loaded by the
host. The return value is the data passed to the activation and shutdown
functions as the serverData argument. Returning NULL from the
startup function indicates failure, so even if a module has no real server
data, it should still return something. The module's shutdown function
is called just before the host unloads the module. Any allocated server
data should be freed at this point.
Calling Convention
Functions in the plug-in are called directly by LightWave, and this
is a potentially funky thing in some systems since they may be different
environments. The lwserver.h header file defines an XCALL_
macro that establishes the calling convention for each platform and compiler.
XCALL_ is applied to anything that preceeds the function name
in definitions.
XCALL_( static const char * ) DescLn( LWInstance instance )
{ ...
All functions in your plug-in that can be called by LightWave need the
XCALL_ treatment, with the exception of the startup and shutdown
functions. |