Overlays can be attached to a node, and that node can be a user plugin or an existing RAYZ node - that means that you can define your own interfaces for existing RAYZ nodes, for further customization.
When an Overlay is not attached to any node, it appears in the Image
Viewer menu, and becomes available as an overlay at any time.
For example, the builtin overlay for displaying Video Safe is an
overlay that is not attached to any node:
Overlays are described, as usual, by a structure, in this case the OverlayInfo structure. This looks like this:
static RPI_OverlayInfo oinfo = { { "internal name", "menu name", "author", "version" }, Init, Shutdown, CreateInstance, DestroyInstance, SourceChanged, FullSizeChanged, SourceOutOfDate, OverlayRender, OverlayLeftMouseDown, OverlayLeftMouseDrag, OverlayLeftMouseUp, OverlayMouseEnter, OverlayMouseDrag, OverlayMouseExit, attach_to_node };This structure must be registered, as with the node and image op structures. This is accomplished with the cpiRegisterOverlay() call. The structure must also be unregistered when you exit RAYZ, with the cpiUnregisterOverlay() call. These would typically look like the following:
CPIDSOEXPORT CPI_Bool rpiPluginInit( void ) { CPI_Bool retval = CPI_TRUE; // you register with the structure's address retval = cpiRegisterImageOp( &opinfo ); if ( retval ) retval = cpiRegisterNode( &ninfo ); if ( retval ) retval = cpiRegisterOverlay( &oinfo ); return retval; } ////////////////////////////////////////////// // unregister everything void upiPluginCleanup( void ) { // you unregister with the internal name cpiUnregisterImageOp( "cropcircle" ); cpiUnregisterNode( "cropcircle" ); cpiUnregisterOverlay( "cropcircle" ); }
The fields in the overlay structure have the following meanings:
Initialize - Function called once when RAYZ starts up.
Shutdown - Function called once when RAYZ shuts down.
CreateInstance - This function creates an instance of the overlay being defined, generally by allocating a private data structure. This will be used for node overlays, because you can have more than one instance of a node and their state need to be kept distinct. For image viewer overlays, this is less likely to be needed, because even though you can have multiple viewers, the overlays are not likely to have parameters and/or states.
For example, in the CropCircle source, we need to keep track of a circle - its center and radius, plus some other state information. We can use the concept of private data to do this, as follows:
#define CIRCLE_ID 1 #define CROSS_ID 2 typedef struct _overlayState { CPI_Float32 centerX; CPI_Float32 centerY; CPI_Float32 radius; CPI_Float32 startRad; CPI_Uint32 selectedObject; CPI_Float32 myTime; } overlayState; ////////////////////////////////////// // This creates the overlay you are working with, by allocating // the defined data structure and passing it on. CPI_PrivateData CropCircleCreateInstance( void ) { overlayState *retval; retval = (overlayState *)cpiAlloc( sizeof( overlayState ) ); return retval; }Now whenever a private data 'handle' is passed into a user-define routine, the information in the structure will be available. Please refer to the CropCircle.C and CircleRamp.C examples.
DestroyInstance - This is the place to return any memory allocated in CreateInstance(). For example, you might do something like this:
void CropCircleDestroyInstance( CPI_PrivateData handle ) { overlayState *state = (overlayState *)handle; cpiFree( state ); }
SourceChanged - This is called when the input image changes, to allow any values which are based on the image attributes (mainly size, but not only) to be updated.
FullSizeChanged - This is called when the size of the input changes. This is different from SourceChanged because the same source node/image may be connected, but that image may change size for any number of reasons.
SourceOutOfDate - If the node (or image viewer) is asked to recompute for any reason (such as a parameter change, either in this node or elsewhere in RAYZ), this routine is called. This is from the example in CropCircle.C:
void CropCircleSourceOutOfDate( CPI_PrivateData handle, CPI_ImageContext fullsize, CPI_Float32 theTime ) { overlayState *state = (overlayState *)handle; cpiGetFloat( &state->centerX, "center.x", theTime ); cpiGetFloat( &state->centerY, "center.y", theTime ); cpiGetFloat( &state->radius, "radius", theTime ); state->myTime = theTime; }
OverlayRender -
This is the user-defined rendering routine. The programmer has available
a number of standard 2D drawing routines - these are given as follows.
Specific arguments are defined after the table.
Graphics Routines | |||
---|---|---|---|
DrawLine | DrawRect | DrawCircle | DrawEllipse |
DrawArc | DrawFilledRect | DrawFilledCircle | DrawFilledEllipse |
DrawFilledArc | DrawText | ||
Arbitrary Shapes | |||
BeginLine | LineVertex | EndLine | |
BeginPoly | BeginFilledPoly | PolyVertex | EndPoly |
BeginBezier | BezierVertex | EndBezier | |
Utility Functions | |||
StartNewObject | SetColor | DoRedraw | SetSelectLock |
void cpiDrawLine( const CPI_Float32 x1, const CPI_Float32 y1, const CPI_Float32 x2, const CPI_Float32 y2 ) void cpiDrawRect( const CPI_Float32 x, const CPI_Float32 y, const CPI_Float32 w, const CPI_Float32 h ) void cpiDrawFilledRect( const CPI_Float32 x, const CPI_Float32 y, const CPI_Float32 w, const CPI_Float32 h ) void cpiDrawCircle( const CPI_Float32 x, const CPI_Float32 y, const CPI_Float32 r ) void cpiDrawFilledCircle( const CPI_Float32 x, const CPI_Float32 y, const CPI_Float32 r ) void cpiDrawEllipse( const CPI_Float32 x, const CPI_Float32 y, const CPI_Float32 rx, const CPI_Float32 ry ) void cpiDrawFilledEllipse( const CPI_Float32 x, const CPI_Float32 y, const CPI_Float32 rx, const CPI_Float32 ry ) void cpiDrawArc( const CPI_Float32 x, const CPI_Float32 y, const CPI_Float32 r, const CPI_Float32 a, const CPI_Float32 b ) void cpiDrawFilledArc( const CPI_Float32 x, const CPI_Float32 y, const CPI_Float32 r, const CPI_Float32 a, const CPI_Float32 b ) void cpiDrawText( const CPI_Uint32 alignment, const CPI_Float32 x, const CPI_Float32 y, const CPI_Float32 w, const CPI_Float32 h, const char *msg ) where alignment is one of CPI_ALIGN_LEFT CPI_ALIGN_CENTER CPI_ALIGN_RIGHT CPI_ALIGN_BOTTOM_LEFT CPI_ALIGN_BOTTOM_CENTER CPI_ALIGN_BOTTOM_RIGHT CPI_ALIGN_TOP_LEFT CPI_ALIGN_TOP_CENTER CPI_ALIGN_TOP_RIGHT
// Define an arbitrary line void cpiBeginLine( void ); void cpiLineVertex( const CPI_Float32 x, const CPI_Float32 y ); void cpiEndLine( void ); // Define an arbitrary polygon, as outline or solid filled shape void cpiBeginPoly( void ); void cpiBeginFilledPoly( void ); void cpiPolyVertex( const CPI_Float32 x, const CPI_Float32 y ); void cpiEndPoly( void ); // Define an arbitrary bezier shape void cpiBeginBezier( void ); void cpiBezierVertex( const CPI_Float32 x, const CPI_Float32 y ); void cpiEndBezier( void );
// Start the definition of a new object. All subsequent graphics calls // will be associated with this object ID. It is not necessary to close // object - starting an object implies closing the previous one. void cpiStartNewObject( CPI_Uint32 objectID ) // Set the current color. This color is associated with all subsequent // graphics calls void cpiSetColor( const CPI_Float32 red, const CPI_Float32 green, const CPI_Float32 blue ); // Force a redraw of all defined objects - programmers must explicitly // call this routine void cpiDoRedraw( void ); // Lock the current object, to prevent picking void cpiSetSelectLock( CPI_Bool lock );
Here is an example from the CropCircle node:
void CropCircleRender( CPI_PrivateData handle, CPI_Bool isPicking ) { CPI_Float32 radius; overlayState *state = (overlayState *)handle; // state is a local pointer to our private data structure radius = state->radius * 0.5; if ( radius <= 0 ) radius = 0.075; if ( radius > 1 ) radius = 1; // each collection of lines or shapes that you want to be // separately selectable should be delimited by a call to // cpiStartNewObject. The ID that you pass will be returned // in the selection routine, so you know what the user has // selected. cpiStartNewObject( CIRCLE_ID ); cpiSetColor( 0.1, 0.1, 1.0 ); cpiDrawCircle( state->centerX, state->centerY, radius ); // define a second 'object' cpiStartNewObject( CROSS_ID ); cpiDrawLine( state->centerX - 0.05, state->centerY, state->centerX + 0.05, state->centerY ); cpiDrawLine( state->centerX, state->centerY - 0.05, state->centerX, state->centerY + 0.05 ); }
OverlayLeftMouseDown -
This routine, and the ones following, are called to service the
appropriate hardware activity. They are only called if you have a current
object under the cursor. The input values for each are
handle | pointer to your private data structure |
objectID | the ID of the overlay image that is under the cursor |
x, y | the current x,y position of the cursor, in the range 0.0 - 1.0 |
keyMod | any modifier key with is pressed, one of CPI_CTRL_KEY, CPI_ALT_KEY or CPI_SHIFT_KEY. |
As a general rule, the mouse down updates values and locks the current object, the mouse drag then updates node values, and the mouse up unlocks the current selection.
For example, here is the MouseDown() routine from CropCircle.C
void CropCircleLeftMouseDown( CPI_PrivateData handle, CPI_Uint32 objectID, CPI_Float32 x, CPI_Float32 y, CPI_Uint32 keyMod ) { overlayState *state = (overlayState *)handle; state->selectedObject = objectID; // compute radius to here, and store difference as error // factor for mouse dragging state->startRad = getRad( x, y, state->centerX, state->centerY ); // prevent other objects from getting events, for example // if you drag this one across another one cpiSetSelectLock( CPI_TRUE ); }
OverlayLeftMouseDrag - See OverlayLeftMouseDown.
OverlayLeftMouseUp - See OverlayLeftMouseDown.
OverlayMouseEnter - This routine and the next two (Drag and Exit) provide entry points for mouse activity which does not involve holding down the mouse button. You might want to know this to take care of highlighting selectable objects, for example. See the header file CPI_OverlayProvider.h for syntax.
OverlayMouseDrag - This is called while the mouse is moving over an object which was previously entered.
OverlayMouseExit - This is called when the mouse leaves an object.
attach_to_node - This is a string, which is the internal name (not the menu name) of the node to attach this overlay to.
If this string is NULL, the overlay appears in the Image Viewer overlay menu, along with RAYZ own built-in overlays. This is how the Mask185.C overlay works - this source example masks out portions of the image outside of the 1:1.85 ratio.
RAYZ does not care if the node name is a plugin or one of its own built-in nodes, so in theory you can attach your own overlays to RAYZ's nodes, such as brightness. In order to facilitate this, the internal names of all RAYZ nodes are given below.
add | atop | bitdepth | blur | brightness | bumpmap | channelswap | chromakey |
color | colorbars | colorcorrect | colorcurves | comment | contrast | convolve | cornerpin |
crop | degrain | deinterlace | diff | dissolve | edge | emboss | erodedilate |
fstops | flipflop | gamma | gradient | grain | hueadjust | imagein | indexedcolor |
inside | interlace | invert | lintolog | logtolin | lumakey | matchmove | multicomp |
merge | meters | minmax | monochrome | multiply | group | noise | outside |
over | posterize | premultiply | printerlights | pulldown | pushup | rank | resize |
roto | screen | sequence | sharpen | skew | split | stabilize | subtract |
switch | text | timeblur | track | transform | ultimatte | ultimatte_ae | ultimatte_cc |
ultimatte_csc | ultimatte_gk | unpremultiply | unsharpmask | under | variableblur | vectorblur | vectorwarp |
videosafe | xpresso | zcomp |
See CircleRamp.C, SimpleOverlay.C and Mask185.C for examples.