#ifdef WIN32
#include <windows.h>
#endif
#include <cstring>
#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
#include <cmath>
#include <stdexcept>
#include <new>
#include "ofxImageEffect.h"
#include "ofxMemory.h"
#include "ofxMultiThread.h"
#include "../include/ofxUtilities.H"
#if defined __APPLE__ || defined linux || defined __FreeBSD__
# define EXPORT __attribute__((visibility("default")))
#elif defined _WIN32
# define EXPORT OfxExport
#else
# error Not building on your operating system quite yet
#endif
#define kPointParam "point"
OfxHost *gHost;
OfxImageEffectSuiteV1 *gEffectHost = 0;
OfxPropertySuiteV1 *gPropHost = 0;
OfxParameterSuiteV1 *gParamHost = 0;
OfxMemorySuiteV1 *gMemoryHost = 0;
OfxMultiThreadSuiteV1 *gThreadHost = 0;
OfxMessageSuiteV1 *gMessageSuite = 0;
OfxInteractSuiteV1 *gInteractHost = 0;
static OfxStatus
isIdentity(OfxImageEffectHandle ,
OfxPropertySetHandle ,
OfxPropertySetHandle outArgs)
{
gPropHost->propSetString(outArgs, kOfxPropName, 0, kOfxImageEffectSimpleSourceClipName);
return kOfxStatOK;
}
static OfxStatus render(OfxImageEffectHandle ,
OfxPropertySetHandle ,
OfxPropertySetHandle )
{
return kOfxStatOK;
}
struct MyInteractData {
bool selected;
OfxParamHandle pointParam;
explicit MyInteractData(OfxParamHandle pParam)
: selected(false)
, pointParam(pParam)
{
}
};
static MyInteractData *
getInteractData(OfxInteractHandle interactInstance)
{
void *dataV = ofxuGetInteractInstanceData(interactInstance);
return (MyInteractData *) dataV;
}
static OfxStatus
interactDescribe(OfxInteractHandle )
{
return kOfxStatOK;
}
static OfxStatus
interactCreateInstance(OfxImageEffectHandle pluginInstance,
OfxInteractHandle interactInstance)
{
OfxParamSetHandle paramSet;
gEffectHost->getParamSet(pluginInstance, ¶mSet);
OfxParamHandle pointParam;
gParamHost->paramGetHandle(paramSet, kPointParam, &pointParam, 0);
MyInteractData *data = new MyInteractData(pointParam);
ofxuSetInteractInstanceData(interactInstance, (void *) data);
OfxPropertySetHandle interactProps;
gInteractHost->interactGetPropertySet(interactInstance, &interactProps);
gPropHost->propSetString(interactProps, kOfxInteractPropSlaveToParam, 0, kPointParam);
return kOfxStatOK;
}
static OfxStatus
interactDestroyInstance(OfxImageEffectHandle ,
OfxInteractHandle interactInstance)
{
MyInteractData *data = getInteractData(interactInstance);
delete data;
return kOfxStatOK;
}
#define kXHairSize 10
static OfxStatus
interactDraw(OfxImageEffectHandle pluginInstance,
OfxInteractHandle interactInstance,
OfxPropertySetHandle drawArgs)
{
MyInteractData *data = getInteractData(interactInstance);
double pixelScale[2];
ofxuGetInteractPixelScale(drawArgs, pixelScale);
double x, y;
gParamHost->paramGetValue(data->pointParam, &x, &y);
float dx = kXHairSize * pixelScale[0];
float dy = kXHairSize * pixelScale[1];
if(data->selected)
glColor3f(1, 1, 1);
else
glColor3f(1, 0, 0);
glPushMatrix();
glTranslated(x, y, 0);
glBegin(GL_LINES);
glVertex2f(-dx, 0);
glVertex2f(dx, 0);
glVertex2f(0, -dy);
glVertex2f(0, dy);
glEnd();
glPopMatrix();
return kOfxStatOK;
}
static OfxStatus
interactPenMotion(OfxImageEffectHandle pluginInstance,
OfxInteractHandle interactInstance,
OfxPropertySetHandle inArgs)
{
MyInteractData *data = getInteractData(interactInstance);
if(data->selected) {
OfxPointD penPos;
gPropHost->propGetDoubleN(inArgs, kOfxInteractPropPenPosition, 2, &penPos.x);
gParamHost->paramSetValue(data->pointParam, penPos.x, penPos.y);
return kOfxStatOK;
}
return kOfxStatReplyDefault;
}
static OfxStatus
interactPenDown(OfxImageEffectHandle pluginInstance,
OfxInteractHandle interactInstance,
OfxPropertySetHandle inArgs)
{
MyInteractData *data = getInteractData(interactInstance);
double x, y;
gParamHost->paramGetValue(data->pointParam, &x, &y);
double pixelScale[2];
ofxuGetInteractPixelScale(inArgs, pixelScale);
double penPos[2];
gPropHost->propGetDoubleN(inArgs, kOfxInteractPropPenPosition, 2, penPos);
if(fabs(x - penPos[0]) < 5 * pixelScale[0] && fabs(y - penPos[1]) < 5 * pixelScale[1]) {
data->selected = true;
return kOfxStatOK;
}
return kOfxStatReplyDefault;
}
static OfxStatus
interactPenUp(OfxImageEffectHandle ,
OfxInteractHandle interactInstance,
OfxPropertySetHandle )
{
MyInteractData *data = getInteractData(interactInstance);
if(data->selected) {
data->selected = false;
return kOfxStatOK;
}
return kOfxStatReplyDefault;
}
static OfxStatus
overlayMain(const char *action, const void *handle, OfxPropertySetHandle inArgs, OfxPropertySetHandle )
{
OfxInteractHandle interact = (OfxInteractHandle ) handle;
OfxPropertySetHandle props;
gInteractHost->interactGetPropertySet(interact, &props);
if(strcmp(action, kOfxActionDescribe) == 0) {
return interactDescribe(interact);
}
else {
OfxImageEffectHandle pluginInstance;
gPropHost->propGetPointer(props, kOfxPropEffectInstance, 0, (void **) &pluginInstance);
if(strcmp(action, kOfxActionCreateInstance) == 0) {
return interactCreateInstance(pluginInstance, interact);
}
else if(strcmp(action, kOfxActionDestroyInstance) == 0) {
return interactDestroyInstance(pluginInstance, interact);
}
else if(strcmp(action, kOfxInteractActionDraw) == 0) {
return interactDraw(pluginInstance, interact, inArgs);
}
else if(strcmp(action, kOfxInteractActionPenMotion) == 0) {
return interactPenMotion(pluginInstance, interact, inArgs);
}
else if(strcmp(action, kOfxInteractActionPenDown) == 0) {
return interactPenDown(pluginInstance, interact, inArgs);
}
else if(strcmp(action, kOfxInteractActionPenUp) == 0) {
return interactPenUp(pluginInstance, interact, inArgs);
}
return kOfxStatReplyDefault;
}
return kOfxStatReplyDefault;
}
static OfxStatus
describe(OfxImageEffectHandle effect)
{
OfxStatus stat;
if((stat = ofxuFetchHostSuites()) != kOfxStatOK)
return stat;
int supportsOverlays;
gPropHost->propGetInt(gHost->host, kOfxImageEffectPropSupportsOverlays, 0, &supportsOverlays);
if(supportsOverlays == 0)
return kOfxStatErrMissingHostFeature;
OfxPropertySetHandle effectProps;
gEffectHost->getPropertySet(effect, &effectProps);
gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedPixelDepths, 0, kOfxBitDepthByte);
gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedPixelDepths, 1, kOfxBitDepthShort);
gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedPixelDepths, 2, kOfxBitDepthFloat);
gPropHost->propSetString(effectProps, kOfxPropLabel, 0, "OFX Overlay Example");
gPropHost->propSetString(effectProps, kOfxImageEffectPluginPropGrouping, 0, "OFX Example");
gPropHost->propSetString(effectProps, kOfxImageEffectPropSupportedContexts, 0, kOfxImageEffectContextFilter);
gPropHost->propSetPointer(effectProps, kOfxImageEffectPluginPropOverlayInteractV1, 0, (void *) overlayMain);
return kOfxStatOK;
}
static OfxStatus
describeInContext(OfxImageEffectHandle effect, OfxPropertySetHandle )
{
OfxPropertySetHandle props;
gEffectHost->clipDefine(effect, kOfxImageEffectSimpleSourceClipName, &props);
gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 0, kOfxImageComponentRGBA);
gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 1, kOfxImageComponentAlpha);
gEffectHost->clipDefine(effect, kOfxImageEffectOutputClipName, &props);
gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 0, kOfxImageComponentRGBA);
gPropHost->propSetString(props, kOfxImageEffectPropSupportedComponents, 1, kOfxImageComponentAlpha);
OfxParamSetHandle paramSet;
gEffectHost->getParamSet(effect, ¶mSet);
gParamHost->paramDefine(paramSet, kOfxParamTypeDouble2D, kPointParam, &props);
gPropHost->propSetString(props, kOfxParamPropDoubleType, 0, kOfxParamDoubleTypeXYAbsolute);
gPropHost->propSetString(props, kOfxParamPropDefaultCoordinateSystem, 0, kOfxParamCoordinatesNormalised);
gPropHost->propSetDouble(props, kOfxParamPropDefault, 0, 0.5);
gPropHost->propSetDouble(props, kOfxParamPropDefault, 1, 0.5);
gPropHost->propSetString(props, kOfxParamPropHint, 0, "Point attached to overlay crosshair");
gPropHost->propSetString(props, kOfxParamPropScriptName, 0, "point");
gPropHost->propSetString(props, kOfxPropLabel, 0, "Point");
return kOfxStatOK;
}
static OfxStatus
pluginMain(const char *action, const void *handle, OfxPropertySetHandle inArgs, OfxPropertySetHandle outArgs)
{
try {
OfxImageEffectHandle effect = (OfxImageEffectHandle ) handle;
if(strcmp(action, kOfxActionDescribe) == 0) {
return describe(effect);
}
else if(strcmp(action, kOfxImageEffectActionDescribeInContext) == 0) {
return describeInContext(effect, inArgs);
}
else if(strcmp(action, kOfxImageEffectActionIsIdentity) == 0) {
return isIdentity(effect, inArgs, outArgs);
}
else if(strcmp(action, kOfxImageEffectActionRender) == 0) {
return render(effect, inArgs, outArgs);
}
} catch (std::bad_alloc) {
return kOfxStatErrMemory;
} catch ( const std::exception& e ) {
return kOfxStatErrUnknown;
} catch (int err) {
return err;
} catch ( ... ) {
return kOfxStatErrUnknown;
}
return kOfxStatReplyDefault;
}
static void
setHostFunc(OfxHost *hostStruct)
{
gHost = hostStruct;
}
static OfxPlugin basicPlugin =
{
kOfxImageEffectPluginApi,
1,
"uk.co.thefoundry.BasicOverlayPlugin",
1,
0,
setHostFunc,
pluginMain
};
EXPORT OfxPlugin *
OfxGetPlugin(int nth)
{
if(nth == 0)
return &basicPlugin;
return 0;
}
EXPORT int
OfxGetNumberOfPlugins(void)
{
return 1;
}