Files
oak-editor/third_party/openfx/Support/Library/ofxsInteract.cpp
T

547 lines
18 KiB
C++

/** @brief This file contains code that skins the ofx interact suite (for image effects) */
#include "ofxsSupportPrivate.h"
#include <algorithm> // for find
/** @brief The core 'OFX Support' namespace, used by plugin implementations. All code for these are defined in the common support libraries.
*/
namespace OFX {
/** @brief fetch a pixel scale out of the property set */
static OfxPointD getPixelScale(const PropertySet &props)
{
OfxPointD pixelScale;
pixelScale.x = props.propGetDouble(kOfxInteractPropPixelScale, 0);
pixelScale.y = props.propGetDouble(kOfxInteractPropPixelScale, 1);
return pixelScale;
}
/** @brief fetch a render scale out of the property set */
static OfxPointD getRenderScale(const PropertySet &props)
{
OfxPointD v;
v.x = props.propGetDouble(kOfxImageEffectPropRenderScale, 0);
v.y = props.propGetDouble(kOfxImageEffectPropRenderScale, 1);
return v;
}
/** @brief fetch a background colour out of the property set */
static OfxRGBColourD getBackgroundColour(const PropertySet &props)
{
OfxRGBColourD backGroundColour;
backGroundColour.r = props.propGetDouble(kOfxInteractPropBackgroundColour, 0);
backGroundColour.g = props.propGetDouble(kOfxInteractPropBackgroundColour, 1);
backGroundColour.b = props.propGetDouble(kOfxInteractPropBackgroundColour, 2);
return backGroundColour;
}
/** @brief retrieves the image effect pointer from the interact handle */
static ImageEffect *retrieveEffectFromInteractHandle(OfxInteractHandle handle)
{
// get the properties set on this handle
OfxPropertySetHandle propHandle;
OfxStatus stat = OFX::Private::gInteractSuite->interactGetPropertySet(handle, &propHandle);
throwSuiteStatusException(stat);
PropertySet interactProperties(propHandle);
// get the effect handle from this handle
OfxImageEffectHandle effectHandle = (OfxImageEffectHandle) interactProperties.propGetPointer(kOfxPropEffectInstance);
// get the effect properties
return OFX::Private::retrieveImageEffectPointer(effectHandle);
}
/** @brief ctor */
Interact::Interact(OfxInteractHandle handle)
: _interactHandle(handle)
, _effect(0)
{
// get the properties set on this handle
OfxPropertySetHandle propHandle;
OfxStatus stat = OFX::Private::gInteractSuite->interactGetPropertySet(handle, &propHandle);
throwSuiteStatusException(stat);
_interactProperties.propSetHandle(propHandle);
// set othe instance data on the property handle to point to this interact
_interactProperties.propSetPointer(kOfxPropInstanceData, (void *)this);
// get the effect handle from this handle
_effect = retrieveEffectFromInteractHandle(handle);
}
/** @brief ctor */
Interact::~Interact()
{
}
/** @brief The bitdepth of each component in the openGL frame buffer */
int
Interact::getBitDepth(void) const
{
return _interactProperties.propGetInt(kOfxInteractPropBitDepth);
}
/** @brief Does the openGL frame buffer have an alpha */
bool
Interact::hasAlpha(void) const
{
return _interactProperties.propGetInt(kOfxInteractPropHasAlpha) != 0;
}
/** @brief Returns the size of a real screen pixel under the interact's cannonical projection */
OfxPointD
Interact::getPixelScale(void) const
{
OfxPointD v;
v.x = _interactProperties.propGetDouble(kOfxInteractPropPixelScale, 0);
v.y = _interactProperties.propGetDouble(kOfxInteractPropPixelScale, 1);
return v;
}
/** @brief The suggested colour to draw a widget in an interact */
bool
Interact::getSuggestedColour(OfxRGBColourD &c) const
{
// OFX 1.2/1.3 specs say that the host should return kOfxStatReplyDefault if there is no suggested color
OfxStatus stat = OFX::Private::gPropSuite->propGetDouble(_interactProperties.propSetHandle(), kOfxInteractPropSuggestedColour, 0, &c.r);
if (stat != kOfxStatOK) {
return false; // host gave no suggestion (replied kOfxStatReplyDefault or property is unknown to host)
}
stat = OFX::Private::gPropSuite->propGetDouble(_interactProperties.propSetHandle(), kOfxInteractPropSuggestedColour, 1, &c.g);
if (stat != kOfxStatOK) {
return false; // host gave no suggestion (replied kOfxStatReplyDefault or property is unknown to host)
}
stat = OFX::Private::gPropSuite->propGetDouble(_interactProperties.propSetHandle(), kOfxInteractPropSuggestedColour, 2, &c.b);
if (stat != kOfxStatOK) {
return false; // host gave no suggestion (replied kOfxStatReplyDefault or property is unknown to host)
}
return true;
}
/** @brief Request a redraw */
void
Interact::requestRedraw(void) const
{
OfxStatus stat = OFX::Private::gInteractSuite->interactRedraw(_interactHandle);
throwSuiteStatusException(stat);
}
/** @brief Swap a buffer in the case of a double bufferred interact, this is possibly a silly one */
void
Interact::swapBuffers(void) const
{
OfxStatus stat = OFX::Private::gInteractSuite->interactSwapBuffers(_interactHandle);
throwSuiteStatusException(stat);
}
/** @brief Set a param that the interact should be redrawn on if its value changes */
void
Interact::addParamToSlaveTo(Param *p)
{
// do we have it already ?
std::list<Param *>::iterator i;
i = std::find(_slaveParams.begin(), _slaveParams.end(), p);
if(i == _slaveParams.end()) {
// we have a new one to add in here
_slaveParams.push_back(p);
// and set the property
int n = _interactProperties.propGetDimension(kOfxInteractPropSlaveToParam);
_interactProperties.propSetString(kOfxInteractPropSlaveToParam, p->getName(), n);
}
}
/** @brief Remova a param that the interact should be redrawn on if its value changes */
void
Interact::removeParamToSlaveTo(Param *p)
{
// do we have it already ?
std::list<Param *>::iterator i;
i = std::find(_slaveParams.begin(), _slaveParams.end(), p);
if(i != _slaveParams.end()) {
// clobber it from the list
_slaveParams.erase(i);
// reset the property to remove our dead one
_interactProperties.propReset(kOfxInteractPropSlaveToParam);
// and add them all in again
int n = 0;
for(i = _slaveParams.begin(); i != _slaveParams.end(); ++i, ++n) {
_interactProperties.propSetString(kOfxInteractPropSlaveToParam, (*i)->getName(), n);
}
}
}
/** @brief the background colour */
OfxRGBColourD Interact::getBackgroundColour(void) const
{
return OFX::getBackgroundColour(_interactProperties);
}
/** @brief the function called to draw in the interact */
bool
Interact::draw(const DrawArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle pen motion in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::penMotion(const PenArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle pen down events in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::penDown(const PenArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle pen up events in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::penUp(const PenArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle key down events in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::keyDown(const KeyArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle key up events in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::keyUp(const KeyArgs &/*args*/)
{
return false;
}
/** @brief the function called to handle key down repeat events in the interact
returns true if the interact trapped the action in some sense. This will block the action being passed to
any other interact that may share the viewer.
*/
bool
Interact::keyRepeat(const KeyArgs &/*args*/)
{
return false;
}
/** @brief Called when the interact is given input focus */
void
Interact::gainFocus(const FocusArgs &/*args*/)
{
}
/** @brief Called when the interact is loses input focus */
void
Interact::loseFocus(const FocusArgs &/*args*/)
{
}
////////////////////////////////////////////////////////////////////////////////
// overlay interact guff
/** @brief ctor */
OverlayInteract::OverlayInteract(OfxInteractHandle handle)
: Interact(handle)
{
// add this interact into the list of overlays that the effect knows about
if(_effect)
_effect->addOverlayInteract(this);
}
/** @brief ctor */
OverlayInteract::~OverlayInteract()
{
// add this interact into the list of overlays that the effect knows about
if(_effect)
_effect->removeOverlayInteract(this);
}
////////////////////////////////////////////////////////////////////////////////
/** @brief ctor */
InteractArgs::InteractArgs(const PropertySet &props)
{
time = props.propGetDouble(kOfxPropTime);
renderScale = getRenderScale(props);
}
/** @brief ctor */
DrawArgs::DrawArgs(const PropertySet &props)
: InteractArgs(props)
{
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
viewportSize.x = props.propGetDouble(kOfxInteractPropViewportSize, 0, false);
viewportSize.y = props.propGetDouble(kOfxInteractPropViewportSize, 1, false);
#endif
backGroundColour = getBackgroundColour(props);
pixelScale = getPixelScale(props);
}
/** @brief ctor */
PenArgs::PenArgs(const PropertySet &props)
: InteractArgs(props)
{
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
viewportSize.x = props.propGetDouble(kOfxInteractPropViewportSize, 0, false);
viewportSize.y = props.propGetDouble(kOfxInteractPropViewportSize, 1, false);
#endif
pixelScale = getPixelScale(props);
backGroundColour = getBackgroundColour(props);
penPosition.x = props.propGetDouble(kOfxInteractPropPenPosition, 0);
penPosition.y = props.propGetDouble(kOfxInteractPropPenPosition, 1);
try {
penViewportPosition.x = props.propGetInt(kOfxInteractPropPenViewportPosition, 0);
penViewportPosition.y = props.propGetInt(kOfxInteractPropPenViewportPosition, 1);
} catch (OFX::Exception::PropertyUnknownToHost&) {
// Introduced in OFX 1.2. Return (-1,-1) if not available
penViewportPosition.x = penViewportPosition.y = -1.;
}
penPressure = props.propGetDouble(kOfxInteractPropPenPressure);
}
/** @brief ctor */
KeyArgs::KeyArgs(const PropertySet &props)
: InteractArgs(props)
{
time = props.propGetDouble(kOfxPropTime);
renderScale = getRenderScale(props);
keyString = props.propGetString(kOfxPropKeyString);
keySymbol = props.propGetInt(kOfxPropKeySym);
}
/** @brief ctor */
FocusArgs::FocusArgs(const PropertySet &props)
: InteractArgs(props)
{
#ifdef kOfxInteractPropViewportSize // removed in OFX 1.4
viewportSize.x = props.propGetDouble(kOfxInteractPropViewportSize, 0, false);
viewportSize.y = props.propGetDouble(kOfxInteractPropViewportSize, 1, false);
#endif
pixelScale = getPixelScale(props);
backGroundColour = getBackgroundColour(props);
}
void ParamInteractDescriptor::setInteractSizeAspect(double asp)
{
_props->propSetDouble(kOfxParamPropInteractSizeAspect , asp);
}
void ParamInteractDescriptor::setInteractMinimumSize(int x, int y)
{
_props->propSetInt(kOfxParamPropInteractMinimumSize, x, 0);
_props->propSetInt(kOfxParamPropInteractMinimumSize, y, 1);
}
void ParamInteractDescriptor::setInteractPreferredSize(int x, int y)
{
_props->propSetInt(kOfxParamPropInteractPreferedSize, x, 0);
_props->propSetInt(kOfxParamPropInteractPreferedSize, y, 1);
}
ParamInteract::ParamInteract(OfxInteractHandle handle, ImageEffect* effect):Interact(handle), _effect(effect)
{}
OfxPointI ParamInteract::getInteractSize() const
{
OfxPointI ret;
ret.x = _interactProperties.propGetInt(kOfxParamPropInteractSize, 0);
ret.y = _interactProperties.propGetInt(kOfxParamPropInteractSize, 1);
return ret;
}
namespace Private {
/** @brief fetches our pointer out of the props on the handle */
static
Interact *retrieveInteractPointer(OfxInteractHandle handle)
{
Interact *instance;
// get the prop set on the handle
OfxPropertySetHandle propHandle;
OfxStatus stat = OFX::Private::gInteractSuite->interactGetPropertySet(handle, &propHandle);
throwSuiteStatusException(stat);
// make our wrapper object
PropertySet props(propHandle);
// fetch the instance data out of the properties
instance = (Interact *) props.propGetPointer(kOfxPropInstanceData);
OFX::Log::error(instance == 0, "Instance data handle in effect instance properties is NULL!");
// need to throw something here
// and dance to the music
return instance;
}
/** @brief The common entry point used by all interacts */
static
OfxStatus
interactMainEntry(const std::string &action,
OfxInteractHandle handle,
PropertySet inArgs,
PropertySet /*outArgs*/)
{
OfxStatus stat = kOfxStatReplyDefault;
// get the interact pointer
Interact *interact = retrieveInteractPointer(handle);
// if one was not made, return and do nothing
if(!interact)
return stat;
if(action == kOfxActionDestroyInstance) {
delete interact;
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionDraw) {
// make the draw args
DrawArgs drawArgs(inArgs);
if(interact->draw(drawArgs))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionPenMotion) {
// make the draw args
PenArgs args(inArgs);
if(interact->penMotion(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionPenDown) {
// make the draw args
PenArgs args(inArgs);
if(interact->penDown(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionPenUp) {
// make the draw args
PenArgs args(inArgs);
if(interact->penUp(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionKeyDown) {
// make the draw args
KeyArgs args(inArgs);
if(interact->keyDown(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionKeyUp) {
// make the draw args
KeyArgs args(inArgs);
if(interact->keyUp(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionKeyRepeat) {
// make the draw args
KeyArgs args(inArgs);
if(interact->keyRepeat(args))
stat = kOfxStatOK;
}
else if(action == kOfxInteractActionGainFocus) {
// make the draw args
FocusArgs args(inArgs);
interact->gainFocus(args);
}
else if(action == kOfxInteractActionLoseFocus) {
// make the draw args
FocusArgs args(inArgs);
interact->loseFocus(args);
}
return stat;
}
/** @brief The main entry for image effect overlays */
OfxStatus interactMainEntry(const char *actionRaw,
const void *handleRaw,
OfxPropertySetHandle inArgsRaw,
OfxPropertySetHandle outArgsRaw,
InteractDescriptor& desc)
{
OFX::Log::print("********************************************************************************");
OFX::Log::print("START overlayInteractMainEntry (%s)", actionRaw);
OFX::Log::indent();
OfxStatus stat = kOfxStatReplyDefault;
try {
// Cast the raw handle to be an image effect handle, because that is what it is
OfxInteractHandle handle = (OfxInteractHandle) handleRaw;
// Turn the arguments into wrapper objects to make our lives easier
OFX::PropertySet inArgs(inArgsRaw);
OFX::PropertySet outArgs(outArgsRaw);
// turn the action into a std::string
std::string action(actionRaw);
// figure the actions
if (action == kOfxActionDescribe) {
OfxPropertySetHandle propHandle;
OfxStatus stat = OFX::Private::gInteractSuite->interactGetPropertySet(handle, &propHandle);
throwSuiteStatusException(stat);
PropertySet interactProperties(propHandle);
desc.setPropertySet(&interactProperties);
desc.describe();
}
else if (action == kOfxActionCreateInstance)
{
// fetch the image effect we are being made for out of the interact's property handle
ImageEffect *effect = retrieveEffectFromInteractHandle(handle);
OFX::Interact* interact = desc.createInstance(handle, effect);
(void)interact;
// and all was well
stat = kOfxStatOK;
}
else {
stat = interactMainEntry(action, handle, inArgs, outArgs);
}
}
catch(...)
{
stat = kOfxStatFailed;
}
OFX::Log::outdent();
OFX::Log::print("STOP overlayInteractMainEntry (%s)", actionRaw);
return stat;
}
}; // end namespace private
}; // end of namespace