Function Modules


ExpressionFunction.gif

Introduction
Next to commands, functions are the easiest type of module to write for a messiah plugin. To avoid confusion with C functions we will refer to messiah function modules as "Function Modules". Like C functions, Function Modules accept arguments and return a value. Some Function Modules will serve only to compute some output (return value) based on it's input (arguments), others will perform some action and may also return some meaningful value. Function Modules are Non-Access Based Modules, that is they do not respond to Access Notifications.
You Called?
Messiah functions can be called by the user in several possible ways. The first, and perhaps most familiar to the majority of messiah users is through Command Mode. There Function Modules are called from expressions whenever the scene needs to update itself (such as resulting from a time change.) Another way to call a Function Module is through scripts. Finally, the user may call your Function Module from messiah's command line, this would generally be for functions that perform some action "on demand".
There is one other way that your Function Module may be called, and that is by other plugins. You may, at your discression, "publish" your Function Module so that it may be called by other plugins.
Function Description
As with all module types, you will want to provide a description for your function so that the user can easily determine what it does, and how they should use it. This description will appear in Command Mode in the Functions block when the user has selected your Function Module from the list of available Function Modules. It is a good idea to provide information about each argument in this description. Prior to your Function Module's registration call fxFunctionDescription() to provide this information:

fxFunctionDescription("My function description...", FX_NOFLAG);
Note that we use fxFunctionDescription() instead of fxModuleDescription() which is used for Access Based Modules..
Arguments
You will need to tell messiah what arguments your Function Module accepts, as well as their names, default values or a command to execute to provide those default values. Before you register your Function Module you will call one or more of the fxFunctionArg* functions to tell messiah about the arguments you expect. The order that you call them in is the order they will appear in messiah's interface.

fxFunctionArgInt("an_int", 5, NULL);
fxFunctionArgString("a_string", "empty", NULL);
Here we would have a function that takes two arguments and would look like:
functionName( int an_int = 5, string a_string = "empty" );
The initial value that you provide for each argument is the value that will appear in the edit fields of the Function block. It may be nescessary to set the default value by calling some command instead if the value is not known ahead of time. Consider an object argument, it might be desirable to have the default value of this argument be that of the currently selected object. Obviously this value isn't known ahead of time, but can be determined very easily by executing a command. Here you would just pass FX_NULLID as the default value but provide a default command, in this case "CurObject()", to be executed when your Function Module is chosen from the list:

fxFunctionArgObj("target", FX_NULLID, "CurObject()");
Registering Your Function
To register your Function Module with messiah you will use the fxFunctionRegister() function instead of the fxModuleRegister() function which is used for Access Based Modules.
For example, a Function Module called "MyFuncName" that returns an int might look something like:

fxFunctionRegister("MyFuncName", &exp_func, &publish_func, FX_ARG_INT, FX_NOFLAG);
The first argument is the name of the Function Module, the second and third we will get to shortly, the fourth is the return type of the Function Module (see messiah_arg.h for all valid types) and the last is a flag. If you want this Function Module to be limited to scripts and the command line only (i.e. it cannot be called from expressions) then you will pass FX_FUNC_SCRIPTSONLY as flags.
Function Module Response Function
The actual calculation of your Function Module is handled by a user-defined function called the exp_func(). This function, which is declared/defined with the FX_EXPFUNC() is called every time messiah needs to execute your Function Module. The two arguments to this function are storage for the return value and a structure containing all of the arguments passed to your Function Module. We will deal with each of these items separatly in a moment.
Published Function
If you choose to publish your Function Module for other plugins to use then you will need to write another function, called the publish_func(). The publish_func() is a function that looks exactly like the Function Module itself, for example if you created an Function Module that returns an object and accepts an int, the publish_func() would look like:

FXobject MyPublishFunc(FXint input);
You would pass the address of this function to fxFunctionRegister() as the func parameter. It is also almost certain that you would want to make this function do all of the calculations and simply have the exp_func() delegate to it:

FXobject MyPublishFunc(FXint input)
{
        // do actual calculation
        //...
}

FX_EXPFUNC(MyExpFunc, MyFuncData, arg_data)
// FXint MyExpFunc(FX_Arg *return_arg, MyFuncData *arg_data)
{
        fxArgSetObj(return_arg, 0, MyPublishFunc(arg_data->input));
        
        return FX_FUNC_OK;
}
Return Values
Most Function Modules will probably need to return a value of some sort, even if only to indicate success or failure. Your exp_func() get's passed an FX_Arg * called return_arg that will hold your return value. Use the fxArgSet* functions found in ARG to set this value. Since Function Modules can only return one value the ID parameter of this function will always be 0 as in the example above.
Retrieving Arguments
Your exp_func() will also get a pointer to a structure that holds all of the arguments passed to the Function Module. The name and type of the structure will depend on what you pass to FX_EXPFUNC() as ed and dt respectively. You will need to define this structure yourself and do so in a very specific way. The elements of your structure MUST be arranged in the same order that they are declared using the fxFunctionArg* functions. Failure to follow this rule will have very nasty results indeed!

typedef struct MyData_St
{
        FXobject        o;
        FXint           i;
        FXdouble        d;
}MyData;

_pluginEntry()
{
        //...
        fxFunctionArgObj("Arg1", FX_NULLID, NULL);
        fxFunctionArgInt("Arg2", 0, NULL);
        fxFunctionArgDouble("Arg3", 0.0, NULL);
        fxFunctionRegister("MyFuncName", &exp_func, &publish_func, FX_ARG_INT, FX_NOFLAG);
        //...
}
As you can see the alignment of the structure matches the order of the argument declaration calls. The exp_func() for this Function Module might look something like:

FX_EXPFUNC(MyExpFunc, MyData, arg_data)
{
        fxArgSetInt( return_arg, 0, MyPublishFunc( arg_data->o, arg_data->i, arg_data->d ) );
        return FX_FUNC_OK;
}
Again this function delegates to some other function who's signature matches that of the Function Module itself. Each of the argument structure elements are filled in with whatever values the user passed to the Function Module in messiah.


© 2003 pmG WorldWide, LLC.


www.projectmessiah.com

groups.yahoo.com/pmGmessiah

Last Updated on Thu Jul 10 04:49:36 2003