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.
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. |