CommandSequence
Availability LightWave 6.0 | Component Modeler | Header lwcmdseq.h
Command sequence plug-ins issue commands to create and manipulate geometry in Modeler. They also have access to the same mesh editing functions as the MeshDataEdit class.
Activation Function
XCALL_( int ) MyCmdSeq( long version, GlobalFunc *global, LWModCommand *local, void *serverData );
The local
argument to a command sequence's activation function is an
LWModCommand.
typedef struct st_LWModCommand { void *data; const char *argument; LWCommandCode (*lookup) (void *, const char *cmdName); int (*execute) (void *, LWCommandCode cmd, int argc, const DynaValue *argv, EltOpSelect, DynaValue *result); MeshEditBegin *editBegin; int (*evaluate) (void *, const char *command); } LWModCommand;
data
- An opaque pointer to data used internally by Modeler. Pass this as the first argument to
the
lookup
,execute
andevaluate
functions. argument
- Users and other plug-ins can invoke your plug-in with arguments, which are stored here as a string.
cmdcode = lookup( data, cmdname )
- Returns an integer code corresponding to the command name. The command is issued by
passing the command code to the
execute
function. Command codes are constant for a given Modeler session, so this only needs to be called once per command, after which the codes can be cached and then used in any number of calls toexecute
. result = execute( data, cmdcode, argc, argv, selection, cmdresult )
- Issue the command given by the command code argument.
argv
is an array of DynaValue arguments.argc
is the number of arguments in theargv
array. The selection determines which geometry will be affected by the command and can be any one of the EltOpSelect codes exceptOPSEL_MODIFY
. The result of the command is written incmdresult
. The function returnsCSERR_NONE
(0) if it succeeds or one of the following non-zero error codes.CSERR_MEMORY CSERR_IO CSERR_USERABORT CSERR_ARGCOUNT CSERR_ARGTYPE CSERR_ARGVALUE CSERR_OPFAILURE CSERR_BADSEL
edit = editBegin( pnt_bufsize, pol_bufsize, opsel )
- Begin a mesh edit. The buffer sizes are used to create temporary buffers associated with
each point and polygon. Modeler allocates and frees this memory for you, and you can use
it for any per-point or per-polygon data you might need during the edit. Points and
polygons are flagged as selected according to the code you pass in
opsel
.The
editBegin
function is identical to the function passed as the local data to mesh edit plug-ins. See that page for complete documentation of the MeshEditOp structure it returns. Command sequence plug-ins can perform multiple mesh edits. Each edit begins by calling this function to get a MeshEditOp and ends when the MeshEditOp'sdone
function is called. No commands can be issued during a mesh edit. - result = evaluate( data, cmdstring )
- Issue the command with the name and arguments in the command string. This is an
alternative to using
lookup
andexecute
. The command and its arguments are written to a single string and delimited by spaces.
See the Commands pages for a complete list of the
commands that can be issued in Modeler, as well as a detailed explanation of the
formatting of command arguments for both the execute
and evaluate
methods.
Example
The DNA sample is a CommandSequence plug-in that builds classic Watson-Crick DNA molecules. It uses the ModLib static-link library, which greatly simplifies command execution by translating commands into function calls. The library currently contains about 170 functions that cover Modeler commands, mesh edit functions, and globals.
This ModLib function executes the MAKEBALL
command, building the DynaValue
argument list and calling the lookup
and execute
functions. (ModData is
a ModLib structure that caches the LWModCommand pointer and the data returned from a
number of globals.)
int csMakeBall( double *radius, int nsides, int nsegments, double *center ) { static LWCommandCode ccode; ModData *md = getModData(); DynaValue argv[ 4 ]; assert( md->edit == NULL ); argv[ 0 ].type = DY_VFLOAT; argv[ 0 ].fvec.val[ 0 ] = radius[ 0 ]; argv[ 0 ].fvec.val[ 1 ] = radius[ 1 ]; argv[ 0 ].fvec.val[ 2 ] = radius[ 2 ]; argv[ 1 ].type = DY_INTEGER; argv[ 1 ].intv.value = nsides; argv[ 2 ].type = DY_INTEGER; argv[ 2 ].intv.value = nsegments; if ( center ) { argv[ 3 ].type = DY_VFLOAT; argv[ 3 ].fvec.val[ 0 ] = center[ 0 ]; argv[ 3 ].fvec.val[ 1 ] = center[ 1 ]; argv[ 3 ].fvec.val[ 2 ] = center[ 2 ]; } else argv[ 3 ].type = DY_NULL; if ( !ccode ) ccode = md->local->lookup( md->local->data, "MAKEBALL" ); md->cmderror = md->local->execute( md->local->data, ccode, 4, argv, md->opsel, &md->result ); return md->cmderror == CSERR_NONE; }
Using ModLib makes DNA's command processing almost as simple as scripting. Below is a code fragment from the function in the DNA plug-in that creates the cylinders representing atomic bonds.
csSetLayer( layer2 ); csSetDefaultSurface( surface_name( snum )); csMakeDisc( r, h, 0, "Y", bond_nsides, bond_nsegments, c ); csRotate( xrot, "X", NULL ); csRotate( yrot, "Y", NULL ); csMove( pt ); rot = 36 * j; csRotate( rot, "Y", NULL ); csCut(); csSetLayer( layer1 ); csPaste();