From BlenderWiki
Writing a Sequence Plugin
In this Section we will write a basic sequence plugin and then go through the steps to use a sequence plugin.
The basics behind a sequence plugin are you are given as inputs 1 to 3 image buffers, as well as some other information, and you output a resulting image buffer.
All the files necessary to develop plugins as well as a few sample plugins can be found in the blender/plugins
directory. You can alternately get a bunch of plugins from here.
Specification
#include <plugin.h>
- Every Blender plugin should include this header file, which contains all of the structures and defines needed to properly work with Blender.
char name[]="Blur";
- A character string containing the plugin name.
VarStruct varstr[]= {...};
- The varstr contains all of the information Blender needs to display buttons for a plugin. Buttons for plugins can be numerical for input data, or text for comments and other information. Plugins are limited to a maximum of 32 variables. Each VarStruct entry consists of a type, name, range information, and a tool tip.
type
- defines the data type for each button entry, and the way to display the button.
- For number buttons this value should be a combination (binary OR, “
|
”) of “INT
” or “FLO
” for the number format (integer or float), and “NUM
”, “NUMSLI
”, or “TOG
”, for the button type (numeric, numeric with slider, or toggle). - Text buttons should have a type of “
LABEL
”. name
- is what will be displayed on (or beside) the button. This is limited to 15 characters.
range information
- consists of three floats that define the default, minimum, and maximum values for the button. For
TOG
gle buttons, the minimum is set in the pressed state, and the maximum is set in the depressed state. tooltip
- is a string that will be displayed when the mouse is over this button (if the user has Tool Tips on). This has a limit of 80 characters, and should be set to the NULL string (
""
) if unused.
typedef struct Cast {...};
- The
Cast
structure is used in calling thedoit
function, and serves as a way to simply access each plugin’s data values. The cast should contain, in order, an integer or float for every button defined in the varstr, including text buttons. Typically these should have the same name as the button for simple reference.
float cfra
- The
cfra
value is set by Blender to the current frame before every render pass. This value is the frame number (± 0.5 depending on the field settings).
plugin_seq_doit
prototype- The
plugin_seq_doit
function should be prototyped for use by thegetinfo
function. You do not need to change this line.
plugin_seq_getversion
- This function must be in each plugin for it to be loaded correctly. You should not change this function.
plugin_but_changed
- This function is used to pass information about what buttons the user changes in the interface. Most plugins should not need to use this function, only when the interface allows the user to alter some variable that forces the plugin to do recalculation (a random hash table for example).
plugin_init
- If needed plugins may use this function to initialize internal data.
- Note: This init function can be called multiple times if the same plugin sequence is copied. Do not init global data specific to a single instance of a plugin in this function.
plugin_getinfo
- This function is used to communicate information to Blender. You should never need to change it.
plugin_seq_doit
- The sequence
doit
function is responsible for applying the plugin’s effect and copying the final data into the out buffer. - The Arguments
Cast *cast
- The
Cast
structure which contains the plugin data, see thetypedef struct Cast
entry above. float facf0
- The value of the plugin’s Ipo curve for the first field offset. If the user hasn’t made an Ipo curve, this ranges between 0 and 1 for the duration of the plugin.
float facf1
- The value of the plugin’s Ipo curve for the second field offset. If the user hasn’t made an Ipo curve, this ranges between 0 and 1 for the duration of the plugin.
int x, int y
- The width and height of the image buffers, respectively.
Imbuf *ibuf1
- A pointer to the first image buffer the plugin is linked to. This will always be a valid image buffer.
Imbuf *ibuf2
- A pointer to the second image buffer the plugin is linked to. Plugins using this buffer should check for a
NULL
buffer, as the user may not have attached the plugin to two buffers. Imbuf *out
- The image buffer for the plugin’s output.
Imbuf *use
- A pointer to the third image buffer the plugin is linked to. Plugins using this buffer should check for a
NULL
buffer, as the user may not have attached the plugin to three buffers.
ImBuf
image structure- The
ImBuf
structure always contains 32 bits RGBA pixel data.ImBuf
structs are always equal in size, indicated by the passedx
andy
value.
- User Interaction
- There is no way for Blender to know how many inputs a plugin expects, so it is possible for a user to attach only one input to a plugin that expects two. For this reason it is important to always check the buffers your plugin uses to make sure they are all valid. Sequence plugins should also include a text label describing the number of inputs required in the buttons interface.
Generic Sequence Plugin
#include "plugin.h" char name[24]= ""; /* structure for buttons, * {butcode, name, default, min, max, tooltip} */ VarStruct varstr[]= { {LABEL, "In: X strips", 0.0, 0.0, 0.0, ""}, }; /* The cast struct is for input in the main doit function * Varstr and Cast must have the same variables in the same order */ typedef struct Cast { int dummy; /* because of the 'label' button */ } Cast; /* cfra: the current frame */ float cfra; void plugin_seq_doit(Cast *, float, float, int, int, ImBuf *, ImBuf *, ImBuf *, ImBuf *); int plugin_seq_getversion(void) { return B_PLUGIN_VERSION; } void plugin_but_changed(int but) { } void plugin_init() { } void plugin_getinfo(PluginInfo *info) { info->name= name; info->nvars= sizeof(varstr)/sizeof(VarStruct); info->cfra= &cfra; info->varstr= varstr; info->init= plugin_init; info->seq_doit= (SeqDoit) plugin_seq_doit; info->callback= plugin_but_changed; } void plugin_seq_doit(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use) { char *in1= (char *)ibuf1->rect; char *out=(char *)outbuf->rect; }
Our Modifications
The first step is to come up with a game plan. What is this plugin going to do, how are the users going to interact with it. For this example we will create a simple filter that will have a slider for intensity from 0-255. If any of the R,G, or B components of a pixel in the source image are less then our chosen intensity, it will return black and alpha, otherwise it will return whatever is in the image.
Now we’ll copy our generic plugin to simpfilt.c
and will fill in the gaps. Its always a good idea to add some comments. First off tell users what the plugin does, where they can get a copy, who they should contact for bugs/improvements, and any licensing restrictions on the code.
When using comments make sure you use /* */ comments (C style). The plugins are in C and some C compilers do not accept // comments (C++ style).
/*
Description: This plugin is a sample sequence plugin that filters out
lower intensity pixels. It works on one strip as input.
Author: Kent Mein (mein@cs.umn.edu)
Website: http://www.cs.umn.edu/~mein/blender/plugins
Licensing: Public Domain
Last Modified: Sun Sep 7 23:41:35 CDT 2003
*/
Next we need to fill in the name
, you should really keep this the same as your *.c
file. Preferably descriptive, less than 23 chars, no spaces, and all lowercase.
char name[24]= "simpfilt.c";
The Cast and varstr need to be in sync. We want one slider so we’ll do the following:
VarStruct varstr[]= { {LABEL, "In: 1 strips", 0.0, 0.0, 0.0, ""}, {NUM|INT, "Intensity", 10.0, 0.0, 255.0, "Our threshold value"}, }; typedef struct Cast { int dummy; /* because of the 'label' button */ int intensity; } Cast;
Now we need to fill in plugin_seq_doit
. We basically want to loop through each pixel and if RGB are all less than intensity, set the output pixel to (0,0,0,255)
, else set it to the input values for that position.
void plugin_seq_doit(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use) { int nbrComp = xo * yo * 4; /*There are xo times yo pixels, with 4 components for each;*/ int i; char *in1 = (char *)ibuf1->rect; /*ImBuf::rect is an int pointer (containing 4 chars!) */ char *out = (char *)outbuf->rect; for(i=0; i < nbrComp; i+=4) { /* if R and G and B of the pixel are all greater than the intensity, keep it unchanged. */ if((in1[i+0] > cast->intensity) && (in1[i+1] > cast->intensity) && (in1[i+2] > cast->intensity)) { out[i+0] = in1[i+0]; out[i+1] = in1[i+1]; out[i+2] = in1[i+2]; out[i+3] = in1[i+3]; } /* else, make the pixel black and transparent! */ else { out[i+0] = out[i+1] = out[i+2] = 0; out[i+3] = 255; } } }
So we wind up with “simpfilt.c”.
Compiling
“bmake” is a simple utility (shell script) to aid in the compilation and development of plugins, and can be found in the plugins/
sub-directory of the Blender installation directory. It is invoked by: bmake (plugin_name.c)
and will attempt to link the proper libraries and compile the specified C file properly for your system.
If you are trying to develop plugins on a windows machine, bmake may not work for you. In that case you should look into using “lcc”. You can use the following to compile a plugin with lcc:
Assuming you have your plugins in c:\blender\plugins
, here is an example of how you would compile the sequence plugin sweep.c
. Open a dos prompt and do the following (you’ll want to make sure the lcc\bin
directory is in your path):
cd c:\blender\plugins\sequence\sweep
lcc -Ic:\blender\plugins\include sweep.c
lcclnk -DLL sweep.obj c:\blender\plugins\include\seq.def
implib sweep.dll
The latest version of lcc does not have “implib”. Instead, do the following:
cd c:\blender\plugins\sequence\sweep
lcc -Ic:\blender\plugins\include sweep.c
lcclnk -dll -nounderscores sweep.obj c:\blender\plugins\include\seq.def
Note that seq.def
is not distributed with the Blender source but is available from the Blender plugins repository. Alternatively, create a seq.def
file, and copy and paste it the following:
EXPORTS LibMain@12 plugin_but_changed plugin_getinfo plugin_init plugin_seq_doit plugin_seq_getversion