Dynamic RequestAvailability LightWave 6.0 The dynamic request global returns functions that provide a simple user interface API. The requester mechanism predates both the Panels and XPanels systems and is available primarily for backward compatibility. Requesters in LightWave 6.0 and later are implemented as non-modal xpanels, so this global can be used as an alternative method of creating those. Global Call DynaReqFuncs *reqf; reqf = global( LWDYNAREQFUNCS_GLOBAL, GFUSE_TRANSIENT ); The global function returns a pointer to a DynaReqFuncs. typedef struct st_DynaReqFuncs { DynaRequestID (*create) (const char *); int (*addCtrl) (DynaRequestID, const char *, DyReqControlDesc *); DynaType (*ctrlType) (DynaRequestID, int); int (*valueSet) (DynaRequestID, int, DynaValue *); int (*valueGet) (DynaRequestID, int, DynaValue *); int (*post) (DynaRequestID); void (*destroy) (DynaRequestID); LWXPanelID (*xpanel) (DynaRequestID); } DynaReqFuncs;
Control Types These are the kinds of controls you can create.
Control Descriptor The addCtrl function is passed a descriptor to tell it what kind of control to create. For most controls, the descriptor is just a type code corresponding to the DynaType of the variable it represents (one of the types in the list above), but for string, choice and static text controls, some additional information is required to create the control. String typedef struct st_DyReqStringDesc { DynaType type; int width; } DyReqStringDesc;
Choice typedef struct st_DyReqChoiceDesc { DynaType type; const char **items; int vertical; } DyReqChoiceDesc;
Static Text typedef struct st_DyReqTextDesc { DynaType type; const char **text; } DyReqTextDesc;
The control descriptor is a union that collects the type code and this extra information into a single structure. typedef union un_DyReqControlDesc { DynaType type; DyReqStringDesc string; DyReqChoiceDesc choice; DyReqTextDesc text; } DyReqControlDesc; Example This code fragment creates a requester asking for personal information. It relies on functions called reqAdd, reqSet and reqGet to hide some of the details. The source for these functions follows. #include <lwserver.h> #include <lwmodeler.h> DynaRequestID req; int ctl[ 5 ], ok; char name[ 40 ] = "(Your name here)"; int age = 30, gender = 0; double height = 1.8; double measure[ 3 ] = { 0.9144, 0.6096, 0.9144 }; char *glabel[] = { "Female", "Male", NULL }; reqf = global( LWDYNAREQFUNCS_GLOBAL, GFUSE_TRANSIENT ); if ( !reqf ) return AFUNC_BADGLOBAL; req = reqf->create( "All About Me" ); if ( !req ) goto ErrorNoReq; ctl[ 0 ] = reqAdd( req, DY_STRING, "Name", NULL, 20 ); ctl[ 1 ] = reqAdd( req, DY_INTEGER, "Age", NULL, 0 ); ctl[ 2 ] = reqAdd( req, DY_CHOICE, "Gender", glabel, 1 ); ctl[ 3 ] = reqAdd( req, DY_FLOAT, "Height", NULL, 0 ); ctl[ 4 ] = reqAdd( req, DY_VDIST, "Measurements", NULL, 0 ); reqSet( req, ctl[ 0 ], name ); reqSet( req, ctl[ 1 ], &age ); reqSet( req, ctl[ 2 ], &gender ); reqSet( req, ctl[ 3 ], &height ); reqSet( req, ctl[ 4 ], measure ); ok = reqf->post( req ); if ( ok ) { reqGet( req, ctl[ 0 ], name, sizeof( name )); reqGet( req, ctl[ 1 ], &age, 0 ); reqGet( req, ctl[ 2 ], &height, 0 ); reqGet( req, ctl[ 3 ], &gender, 0 ); reqGet( req, ctl[ 4 ], measure, 0 ); } reqf->destroy( req ); The reqAdd function creates a requester control. Most control types can be created with only the DynaType and label, but a few require additional information. The text argument is an array of strings used to create DY_CHOICE and DY_TEXT controls. The extra argument is the string width in characters for DY_STRING controls and the vertical flag for DY_CHOICE controls. int reqAdd( DynaRequestID req, DynaType type, char *label, char **text, int extra ) { DyReqControlDesc desc; desc.type = type; switch ( type ) { case DY_STRING: desc.string.width = extra; break; case DY_CHOICE: desc.choice.items = text; desc.choice.vertical = extra; break; case DY_TEXT: desc.text.text = text; break; default: break; } return reqf->addCtrl( req, title, &desc ); } The reqSet and reqGet functions can set and get the value of any control. The val argument points to a variable of an appropriate type for the control. int reqSet( DynaRequestID req, int ctl, void *val ) { DynaValue dv; int *ivec; double *fvec; dv.type = reqf->ctrlType( req, ctl ); switch ( dv.type ) { case DY_STRING: case DY_SURFACE: dv.str.buf = ( char * ) val; dv.str.bufLen = 0; break; case DY_INTEGER: case DY_BOOLEAN: case DY_FONT: case DY_LAYERS: case DY_CHOICE: dv.intv.value = dv.intv.defVal = *(( int * ) val ); break; case DY_FLOAT: case DY_DISTANCE: dv.flt.value = dv.flt.defVal = *(( double * ) val ); break; case DY_VINT: ivec = ( int * ) val; dv.ivec.val[ 0 ] = ivec[ 0 ]; dv.ivec.val[ 1 ] = ivec[ 1 ]; dv.ivec.val[ 2 ] = ivec[ 2 ]; break; case DY_VFLOAT: case DY_VDIST: fvec = ( double * ) val; dv.fvec.val[ 0 ] = fvec[ 0 ]; dv.fvec.val[ 1 ] = fvec[ 1 ]; dv.fvec.val[ 2 ] = fvec[ 2 ]; break; default: return 0; } return reqf->valueSet( req, ctl, &dv ); } int reqGet( DynaRequestID req, int ctl, void *val, int len ) { DynaValue dv; int *ivec, result; double *fvec; dv.type = reqf->ctrlType( req, ctl ); if ( dv.type == DY_STRING || dv.type == DY_SURFACE ) { dv.str.bufLen = len; } result = reqf->valueGet( req, ctl, &dv ); switch ( dv.type ) { case DY_STRING: case DY_SURFACE: strcpy( val, dv.str.buf ); break; case DY_INTEGER: case DY_BOOLEAN: case DY_FONT: case DY_LAYERS: case DY_CHOICE: *(( int * ) val ) = dv.intv.value; break; case DY_FLOAT: case DY_DISTANCE: *(( double * ) val ) = dv.flt.value; break; case DY_VINT: ivec = ( int * ) val; ivec[ 0 ] = dv.ivec.val[ 0 ]; ivec[ 1 ] = dv.ivec.val[ 1 ]; ivec[ 2 ] = dv.ivec.val[ 2 ]; break; case DY_VFLOAT: case DY_VDIST: fvec = ( double * ) val; fvec[ 0 ] = dv.fvec.val[ 0 ]; fvec[ 1 ] = dv.fvec.val[ 1 ]; fvec[ 2 ] = dv.fvec.val[ 2 ]; break; default: break; } return result; } |