### Dynamic Request Availability LightWave® 6.0 Component Layout, Modeler Header lwdyna.h 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;
`req = create( title )` Create a new dynamic request dialog. The title is displayed at the top of the dialog window. You can create as many dialogs as you like, but only one can be displayed at a time. The requester ID returned by `create` is passed as the first argument to the other requester functions. `ctl = addCtrl( req, label, descriptor )` Add a control to the dialog. Controls are stacked vertically in the requester window in the order in which they're added, with the first control on top. The return value is a control index used to identify the control in calls to `ctrlType`, `valueSet` and `valueGet`. The descriptor, explained below, contains the control type and other information necessary for its display. `ctrlType( req, ctl )` Returns the type of a control. `valueSet( req, ctl, value )` Initialize the value of a control. Values are expressed as DynaValues. This function will return an error code if the DynaValue type is incompatible with the type of the control, or if the control doesn't exist. `valueGet( req, ctl, value )` Retrieve the value of a control. This function will return an error code if the DynaValue type is incompatible with the type of the control, or if the control doesn't exist. `result = post( req )` Display the requester. This function won't return until the user has dismissed the requester. It returns 1 if the user accepted the inputs and 0 if he or she cancelled them. `destroy( req )` Free the requester and associated resources allocated by `create`. `xpanel( req )` Returns the panel ID for the requester. See the XPanels discussion for more about this. Control Types These are the kinds of controls you can create. `DY_STRING` A single line of editable text. If you just want to display static text on the requester, use a `DY_TEXT` control. `DY_INTEGER DY_FLOAT DY_DISTANCE` Numeric edit fields. Distance controls display length units and handle unit conversions. Internally the value is a floating-point number of meters. `DY_VINT DY_VFLOAT DY_VDIST` Vector edit fields. A vector in this case is an array of three numbers. `DY_BOOLEAN DY_CHOICE` Boolean controls are like checkboxes. Internally their states are stored as integers with values of either 0 or 1. Choice controls are like radio buttons, an array of mutually exclusive booleans. The internal representation is an integer containing a zero-based index into the choice list. `DY_SURFACE` Lets the user choose one of the surfaces currently in Modeler's internal surface list. The underlying data for a surface control is a string containing the surface name. `DY_FONT` Lets the user choose one of the fonts currently in Modeler's internal font list. The underlying data for a font control is an integer index into the font list. `DY_TEXT` Static (read-only) text. Use this to write things on the requester. If you need a text edit field, use a `DY_STRING` control instead. `DY_LAYERS` Lets the users select one or more layers. These are represented internally by set bits in an integer. 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;
`width` The displayed width of the edit field, in characters. Choice
       typedef struct st_DyReqChoiceDesc {
          DynaType         type;
          const char     **items;
          int              vertical;
       } DyReqChoiceDesc;
`items` An array of strings. Each string is the label for a choice. The `valueGet` call will return an index into this array to indicate the selected item. `vertical` A non-zero value will cause the choices to be arranged vertically on the requester. Otherwise, they're arranged horizontally. Static Text
       typedef struct st_DyReqTextDesc {
          DynaType         type;
          const char     **text;
       } DyReqTextDesc;
`text` An array of strings. Each string is displayed on its own line in the requester. 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;
    }