To that end, users can write plugins that are:
In addition, overlays can be attached to user-built nodes, or even to existing RAYZ nodes, to add interactive functionality.
Programmers can also build up complex node operations by chaining together internal RAYZ Image Operations - for example, a plugin which requires image scaling and rotation can use the internal routines for scaling and rotating its input, allowing the programmer to spend time on the parts of the plugin which are unique and interesting.
Finally, RAYZ plugins can read values from, and write values to, the user Preferences. And the plugins can create new Preferences for users to have access to, in order to completely customize RAYZ.
We hope the enclosed documentation and examples will allow you to push RAYZ to do the things you need; help is always available at support@sgrail.com.
If you have existing RAYZ plugins written for 1.0, you will have to modify and recompile them - the next section discusses the changes necessary.
In order to take advantage of these improvements, all 2.0 plugins will need to be recompiled, and most will also need to be edited at least slightly. Fortunately, in most cases these changes amount to mostly boilerplate cut & paste editing.
The major changes are noted here.
CPI_PrivateData cpiCreatePrivateData( const char *opName ); CPI_Bool cpiDestroyPrivateData( CPI_PrivateData data );A quick example of how this works follows.
First, define the collection of parameters that you want to use:
typedef struct _gridState { CPI_Int32 size[2]; CPI_Int32 channels; CPI_Int32 bitdepth; CPI_Int32 lineWidth[2]; CPI_Int32 lineGap[2]; CPI_Float32 bgColor[4]; CPI_Float32 lineColor[4]; } gridState;Then, in the Exec routine, allocate one of these structures and fill it with parameters from the user.
static CPI_ImageOp GridExec( CPI_PrivateData handle, CPI_Float32 myTime, CPI_Uint8 quality, CPI_Uint32 nodeOutput, CPI_Bool viewerOutput, CPI_Float32 scaleX, CPI_Float32 scaleY ) } <snip> // Allocate a parameter structure opData = cpiCreatePrivateData( "grid" ); gridData = (gridState *)opData; if ( NULL != gridData ) { // Get the user parameters and fill in the structure fields if ( cpiGetInteger( &gridData->size[0], "size.w", myTime ) && cpiGetInteger( &gridData->size[1], "size.h", myTime ) && cpiGetInteger( &channels, "chans", myTime ) && cpiGetInteger( &bitdepth, "bits", myTime) && etcNext, you have to define the functions that allocate and deallocate the memory for the parameters. This is new code that was not present in 2.0.
// Allocate the storage static CPI_PrivateData GridCreateOpInstance( void ) { gridState *retval = (gridState *)cpiAlloc( sizeof( gridState ) ); return (CPI_PrivateData)retval; } // Give back the storage when the node is destroyed static CPI_Bool GridDestroyOpInstance( CPI_PrivateData handle ) { CPI_Bool retval = CPI_FALSE; gridState *state = (gridState *)handle; if ( NULL != state ) { cpiFree( state ); retval = CPI_TRUE; } return retval; }Finally, you have to register these new functions in the ImageOpInfo structure, which now looks like this:
static RPI_ImageOpInfo opinfo = { { "grid", // op name "", // not used "Silicon Grail", // author "1.0" // version }, GridCreateOpInstance, // create op instance GridDestroyOpInstance, // destroy op instance GridProcess, // image execution process NULL, // InputRegion GridOutputRegion, // output region NULL, // control processing NULL, // setup processing NULL, // cleanup processing 0, // min inputs CPI_FALSE, // does it multiproc? CPI_FALSE // handle disjoint regions? };This also means that functions that took a metadata object containing parameters about your operation, now take a pointer to the parameter structure. For example, the ProcessImage function used to look like this:
static CPI_Bool GridProcess( CPI_Image *result, CPI_Image inputs[], CPI_Uint32 numInputs, CPI_Metadata myParms ) {This has now become
static CPI_Bool GridProcess( CPI_PrivateData handle, CPI_Image *result, CPI_Image inputs[], CPI_Uint32 numInputs ) {
void NodeInputAdded( CPI_PrivateData handle, CPI_Uint32 inputnum ) void NodeInputRemoved( CPI_PrivateData handle, CPI_Uint32 inputnum )
void cpiStartToolbar( void ); void cpiEndToolbar( const char *name, const char *desc, CPI_Uint32 defAlignment, CPI_Bool allowHorizontal, CPI_Bool allowVertical );The possible alignment values are
void OverlayParmChanged( CPI_PrivateData handle, const char *parmname );This allows a callback from the overlay.
There are also new overlay routines which allow you to get access to the image under the overlay, either before or after it has been processed by the node. This is useful for picking colors, for example:
CPI_Bool cpiGetSourceImage( CPI_Uint32 buffer, CPI_Image *image ); CPI_Bool cpiGetConvertedImage( CPI_Uint32 buffer, CPI_Image *image );And of course, if picking is what you want to do, then you need a way to get the color under the cursor:
void *cpiGetPixel( CPI_Image *image, CPI_Int32 x, CPI_Int32 y );
Button Strip - such as the RGBA button strip that all nodes have Icon Toggle - a toggle with an icon Icon Button - a button with an icon Icon Button Strip - a button strip with icons for each buttonAlso, the signatures for some functions have changed, such as button callbacks and the Exec function itself.
Finally, there is a new parameter type, Binary, which allows a node to create (and save) arbitrary binary data. This is for nodes which need to save and restore large amounts of state information, such as some keyers. This parameter is not visible to the user; it is internal to the plugin.
LUTConfidence( CPI_ImageContext context ) PUTParmChanged( const char *parmname )have now become
LUTConfidence( CPI_PrivateData handle, CPI_ImageContext context ) PUTParmChanged( CPI_PrivateData handle, const char *parmname )
Routines for getting and setting the time.
CPI_Bool cpiSetImageViewerTime( CPI_Float32 curTime ); CPI_Float32 cpiGetImageViewerTime( void ); CPI_Bool cpiGetFlipbookRange( CPI_Float32 *start, CPI_Float32 *end );Routines for creating, executing, and handling the results of separate, user-driven execution lists. These are used in a new example node, Stats.C.
CPI_ImageOp cpiCreateNewExecList( void ); CPI_Bool cpiStartExecution( CPI_ExecCallBackFn cbFunc, CPI_PrivateData pData, CPI_ImageOp last ); void (*CPI_ExecCallBackFn)( CPI_Image *result, CPI_PrivateData caller, CPI_PrivateData opData[], CPI_Uint32 num, CPI_Float32 time );