MAXScript Functions with Optional Arguments

MAXScript functions also support optional arguments, using a mechanism called keyword argument passing. The keyword arguments are placed in the argument list of the C++ function after all the mandatory positional argument, and are preceded by a marker value. The marker value is accessible in the global variable keyarg_marker which has type Value*. The arguments are passed in pairs, a keyword name and the argument's value, in the arg_list array.

There are several macros to help extract keyword arguments defined in the header file maxscrpt/maxscrpt.h. These macros assume that the C++ function implementation uses the parameter names arg_list and count.

Examples

The following 'delete_file' example shows an argument count check, conversion of first argument (arg_list[0]) to a string and the return of MAXScript 'true' or 'false' values.

def_visible_primitive(delete_file, "deleteFile");
 
Value* delete_file_cf(Value** arg_list, int count)
{
  // deleteFile "file_name"
  check_arg_count("deleteFile", 1, count);
  BOOL result = DeleteFile(arg_list[0]->to_string());
  return result ? &true_value : &false_value;
}

The 'file_in' example below shows working with an optional keyword argument 'quiet'. The required argument count is checked with the macro check_arg_count_with_keys() in this case. Two typed value locals are declared, one to hold the temporary FileStream instance and the other to hold the fileIn result.

def_visible_primitive(file_in, "fileIn");
 
Value* file_in_cf(Value** arg_list, int count)
{
  // fileIn "filename" [quiet:true]
  check_arg_count_with_keys("fileIn", 1, count);
 
  // declare local variables
  two_typed_value_locals(FileStream* file, Value* result);
 
  Value* quiet = key_arg_or_default(quiet, &true_value);
  type_check(quiet, Boolean, "fileInquiet:");
  Value* result;
 
  // open a temporary fileStream
  vl.file = (new FileStream)->open( arg_list[0]->to_string(), "rt");
  if (vl.file == (FileStream*)&undefined)
  throwRuntimeError (GetString(IDS_FILEIN_CANT_OPEN_FILE), arg_list[0]);
 
  // pass it to the stream-based file_in
  try
  {
    vl.result = file_in(vl.file, (quiet == &true_value));
  }
  catch (...)
  {
    // catch any errors and close the temp filestream
    vl.file->close();
    throw;
  }
 
  // pop value locals & return fileIn result
  return_value(vl.result);
}