1 #ifndef _ofxsInteract_H_ 2 #define _ofxsInteract_H_ 3 /* 4 OFX Support Library, a library that skins the OFX plug-in API with C++ classes. 5 Copyright (C) 2004-2005 The Open Effects Association Ltd 6 Author Bruno Nicoletti bruno@thefoundry.co.uk 7 8 Redistribution and use in source and binary forms, with or without 9 modification, are permitted provided that the following conditions are met: 10 11 * Redistributions of source code must retain the above copyright notice, 12 this list of conditions and the following disclaimer. 13 * Redistributions in binary form must reproduce the above copyright notice, 14 this list of conditions and the following disclaimer in the documentation 15 and/or other materials provided with the distribution. 16 * Neither the name The Open Effects Association Ltd, nor the names of its 17 contributors may be used to endorse or promote products derived from this 18 software without specific prior written permission. 19 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 24 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 The Open Effects Association Ltd 32 1 Wardour St 33 London W1D 6PA 34 England 35 36 37 38 */ 39 40 /** @file This file contains core code that wraps OFX 'objects' with C++ classes. 41 42 This file only holds code that is visible to a plugin implementation, and so hides much 43 of the direct OFX objects and any library side only functions. 44 */ 45 #include "ofxsParam.h" 46 47 #include <list> 48 49 /** @brief Nasty macro used to define empty protected copy ctors and assign ops */ 50 #define mDeclareProtectedAssignAndCC(CLASS) \ 51 CLASS &operator=(const CLASS &) {assert(false); return *this;} \ 52 CLASS(const CLASS &) {assert(false); } 53 54 /** @brief The core 'OFX Support' namespace, used by plugin implementations. All code for these are defined in the common support libraries. 55 */ 56 namespace OFX { 57 58 /** @brief forward declaration */ 59 class ImageEffect; 60 61 /// all image effect interacts have these argumens 62 struct InteractArgs { 63 /// ctor 64 InteractArgs(const PropertySet &props); 65 double time; /**< @brief The current effect time to draw at */ 66 OfxPointD renderScale; /**< @brief The current render scale being applied to any image that would be fetched */ 67 #ifdef OFX_EXTENSIONS_NUKE 68 int view; /**< @brief The current effect view to draw onto */ 69 #endif 70 #ifdef OFX_EXTENSIONS_NATRON 71 bool hasPickerColour; /**< @brief If true, the pickerColour is valid and may be used */ 72 OfxRGBAColourD pickerColour; /**< @brief The picked colour */ 73 74 /**@brief pixel ratio of the screen, typically 2 for Retina screen. Should be used for functions using screen pixels such as glPointSize, glLineWidth, etc...*/ 75 double screenPixelRatio; 76 #endif 77 }; 78 79 /** @brief struct to pass arguments into OFX::Interact::draw */ 80 struct DrawArgs : public InteractArgs { 81 DrawArgs(const PropertySet &props); 82 83 #ifdef kOfxInteractPropViewportSize // removed in OFX 1.4 84 OfxPointD viewportSize; /**< @brief The openGL viewport size for the instance */ 85 #endif 86 OfxPointD pixelScale; /**< @brief The size of a real screen pixel under the interact's canonical projection */ 87 OfxRGBColourD backGroundColour; /**< @brief The current background colour, ignore the A */ 88 }; 89 90 /** @brief POD to pass arguments into OFX::Interact pen actions */ 91 struct PenArgs : public InteractArgs { 92 PenArgs(const PropertySet &props); 93 94 #ifdef kOfxInteractPropViewportSize // removed in OFX 1.4 95 OfxPointD viewportSize; /**< @brief The openGL viewport size for the instance */ 96 #endif 97 OfxPointD pixelScale; /**< @brief The size of a real screen pixel under the interact's canonical projection */ 98 OfxRGBColourD backGroundColour; /**< @brief The current background colour, ignore the A */ 99 OfxPointD penPosition; /**< @brief The current pen position */ 100 OfxPointD penViewportPosition;/**< @brief The current pen position in viewport coordinates */ 101 double penPressure; /**< @brief The normalised pressure on the pen */ 102 }; 103 104 /** @brief struct to pass arguments into OFX::Interact key actions 105 106 Note 107 - some keys cannot be represented as UTF8 strings (eg: the key pad page down key kOfxKey_KP_Page_Up), in which case the key string will be set to "". 108 - some UTF8 symbols (generally non-English language ones) cannot be represented by one of the keySymbols, in which case the UTF8 string will be set to some non empty value, but the keySymbol will be set to kOfxKey_Unknown. 109 - in no case will keyString be set to "" and keySymbol be set to kOfxKey_Unknown. 110 */ 111 struct KeyArgs : public InteractArgs { 112 KeyArgs(const PropertySet &props); 113 114 int keySymbol; /**< @brief The key represented as one of the entries in ofxKeySyms.h, see note in OFX::KeyArgs */ 115 std::string keyString; /**< @brief That key as a UTF8 string, see note in OFX::KeyArgs */ 116 }; 117 118 /** @brief struct to pass arguments into OFX::Interact focus actions */ 119 struct FocusArgs : public InteractArgs { 120 FocusArgs(const PropertySet &props); 121 122 #ifdef kOfxInteractPropViewportSize // removed in OFX 1.4 123 OfxPointD viewportSize; /**< @brief The openGL viewport size for the instance */ 124 #endif 125 OfxPointD pixelScale; /**< @brief The size of a real screen pixel under the interact's canonical projection */ 126 OfxRGBColourD backGroundColour; /**< @brief The current background colour, ignore the A */ 127 }; 128 129 /** @brief Wraps up an OFX interact object for an Image Effect. It won't work for any other plug-in type at present (it would need to be broken into a hierarchy of classes). 130 */ 131 class InteractAbstract { 132 public: 133 /** @brief virtual destructor */ ~InteractAbstract()134 virtual ~InteractAbstract() {} 135 136 //////////////////////////////////////////////////////////////////////////////// 137 // override the below in derived classes to do something useful 138 139 /** @brief the function called to draw in the interact */ 140 virtual bool draw(const DrawArgs &args) = 0; 141 142 /** @brief the function called to handle pen motion in the interact 143 144 returns true if the interact trapped the action in some sense. This will block the action being passed to 145 any other interact that may share the viewer. 146 */ 147 virtual bool penMotion(const PenArgs &args) = 0; 148 149 /** @brief the function called to handle pen down events in the interact 150 151 returns true if the interact trapped the action in some sense. This will block the action being passed to 152 any other interact that may share the viewer. 153 */ 154 virtual bool penDown(const PenArgs &args) = 0; 155 156 /** @brief the function called to handle pen up events in the interact 157 158 returns true if the interact trapped the action in some sense. This will block the action being passed to 159 any other interact that may share the viewer. 160 */ 161 virtual bool penUp(const PenArgs &args) = 0; 162 163 /** @brief the function called to handle key down events in the interact 164 165 returns true if the interact trapped the action in some sense. This will block the action being passed to 166 any other interact that may share the viewer. 167 */ 168 virtual bool keyDown(const KeyArgs &args) = 0; 169 170 /** @brief the function called to handle key up events in the interact 171 172 returns true if the interact trapped the action in some sense. This will block the action being passed to 173 any other interact that may share the viewer. 174 */ 175 virtual bool keyUp(const KeyArgs &args) = 0; 176 177 /** @brief the function called to handle key down repeat events in the interact 178 179 returns true if the interact trapped the action in some sense. This will block the action being passed to 180 any other interact that may share the viewer. 181 */ 182 virtual bool keyRepeat(const KeyArgs &args) = 0; 183 184 /** @brief Called when the interact is given input focus */ 185 virtual void gainFocus(const FocusArgs &args) = 0; 186 187 /** @brief Called when the interact is loses input focus */ 188 virtual void loseFocus(const FocusArgs &args) = 0; 189 }; 190 191 class Interact : public InteractAbstract { 192 protected : 193 OfxInteractHandle _interactHandle; /**< @brief The handle for this interact */ 194 PropertySet _interactProperties; /**< @brief The property set on this interact */ 195 std::list<Param *> _slaveParams; /**< @brief List of params we are currently slaved to */ 196 ImageEffect *_effect; /**< @brief The instance we are associated with */ 197 198 public : 199 /** @brief ctor */ 200 Interact(OfxInteractHandle handle); 201 202 /** @brief virtual destructor */ 203 virtual ~Interact(); 204 getProperties()205 PropertySet &getProperties() { return _interactProperties; } 206 207 /** @brief The bitdepth of each component in the openGL frame buffer */ 208 int getBitDepth(void) const; 209 210 /** @brief Does the openGL frame buffer have an alpha */ 211 bool hasAlpha(void) const; 212 213 /** @brief Returns the size of a real screen pixel under the interact's cannonical projection */ 214 OfxPointD getPixelScale(void) const; 215 216 /** @brief The suggested colour to draw a widget in an interact. Returns false if there is no suggestion. */ 217 bool getSuggestedColour(OfxRGBColourD &c) const; 218 219 /** @brief the background colour */ 220 OfxRGBColourD getBackgroundColour(void) const; 221 222 /** @brief Set a param that the interact should be redrawn on if its value changes */ 223 void addParamToSlaveTo(Param *p); 224 225 /** @brief Remova a param that the interact should be redrawn on if its value changes */ 226 void removeParamToSlaveTo(Param *p); 227 228 /** @brief Request a redraw */ 229 void requestRedraw(void) const; 230 231 /** @brief Swap a buffer in the case of a double bufferred interact, this is possibly a silly one */ 232 void swapBuffers(void) const; 233 234 #ifdef OFX_EXTENSIONS_NATRON 235 /** @brief Sets wether the interact uses an additional colour picking value in the inArgs of its actions. */ 236 void setColourPicking(bool useColourPicking); 237 #endif 238 239 //////////////////////////////////////////////////////////////////////////////// 240 // override the below in derived classes to do something useful 241 242 /** @brief the function called to draw in the interact */ 243 virtual bool draw(const DrawArgs &args); 244 245 /** @brief the function called to handle pen motion in the interact 246 247 returns true if the interact trapped the action in some sense. This will block the action being passed to 248 any other interact that may share the viewer. 249 */ 250 virtual bool penMotion(const PenArgs &args); 251 252 /** @brief the function called to handle pen down events in the interact 253 254 returns true if the interact trapped the action in some sense. This will block the action being passed to 255 any other interact that may share the viewer. 256 */ 257 virtual bool penDown(const PenArgs &args); 258 259 /** @brief the function called to handle pen up events in the interact 260 261 returns true if the interact trapped the action in some sense. This will block the action being passed to 262 any other interact that may share the viewer. 263 */ 264 virtual bool penUp(const PenArgs &args); 265 266 /** @brief the function called to handle key down events in the interact 267 268 returns true if the interact trapped the action in some sense. This will block the action being passed to 269 any other interact that may share the viewer. 270 */ 271 virtual bool keyDown(const KeyArgs &args); 272 273 /** @brief the function called to handle key up events in the interact 274 275 returns true if the interact trapped the action in some sense. This will block the action being passed to 276 any other interact that may share the viewer. 277 */ 278 virtual bool keyUp(const KeyArgs &args); 279 280 /** @brief the function called to handle key down repeat events in the interact 281 282 returns true if the interact trapped the action in some sense. This will block the action being passed to 283 any other interact that may share the viewer. 284 */ 285 virtual bool keyRepeat(const KeyArgs &args); 286 287 /** @brief Called when the interact is given input focus */ 288 virtual void gainFocus(const FocusArgs &args); 289 290 /** @brief Called when the interact is loses input focus */ 291 virtual void loseFocus(const FocusArgs &args); 292 }; 293 294 /** @brief an interact for an image effect overlay */ 295 class OverlayInteract : public Interact { 296 public : 297 /** @brief ctor */ 298 OverlayInteract(OfxInteractHandle handle); 299 300 /** @brief dtor */ 301 virtual ~OverlayInteract(); 302 }; 303 304 /** @brief an interact for an image effect overlay made from an InteractAbstract helper class */ 305 template<class InteractHelper1> 306 class OverlayInteractFromHelper : public OFX::OverlayInteract, private InteractHelper1 307 { 308 public: OverlayInteractFromHelper(OfxInteractHandle handle,OFX::ImageEffect * effect)309 OverlayInteractFromHelper(OfxInteractHandle handle, OFX::ImageEffect* effect) 310 : OFX::OverlayInteract(handle) 311 , InteractHelper1(effect, this) 312 { 313 } 314 315 private: draw(const DrawArgs & args)316 virtual bool draw(const DrawArgs &args) { 317 return InteractHelper1::draw(args); 318 } 319 penMotion(const PenArgs & args)320 virtual bool penMotion(const PenArgs &args) { 321 return InteractHelper1::penMotion(args); 322 } 323 penDown(const PenArgs & args)324 virtual bool penDown(const PenArgs &args) { 325 return InteractHelper1::penDown(args); 326 } 327 penUp(const PenArgs & args)328 virtual bool penUp(const PenArgs &args) { 329 return InteractHelper1::penUp(args); 330 } 331 keyDown(const OFX::KeyArgs & args)332 virtual bool keyDown(const OFX::KeyArgs &args) { 333 return InteractHelper1::keyDown(args); 334 } 335 keyUp(const OFX::KeyArgs & args)336 virtual bool keyUp(const OFX::KeyArgs &args) { 337 return InteractHelper1::keyUp(args); 338 } 339 keyRepeat(const KeyArgs & args)340 virtual bool keyRepeat(const KeyArgs &args) { 341 return InteractHelper1::keyRepeat(args); 342 } 343 gainFocus(const FocusArgs & args)344 virtual void gainFocus(const FocusArgs &args) { 345 InteractHelper1::gainFocus(args); 346 } 347 loseFocus(const FocusArgs & args)348 virtual void loseFocus(const FocusArgs &args) { 349 InteractHelper1::loseFocus(args); 350 } 351 }; 352 353 /** @brief an interact for an image effect overlay made from two InteractAbstract helper classes */ 354 template<class InteractHelper1, class InteractHelper2> 355 class OverlayInteractFromHelpers2 : public OFX::OverlayInteract, private InteractHelper1, InteractHelper2 356 { 357 public: OverlayInteractFromHelpers2(OfxInteractHandle handle,OFX::ImageEffect * effect)358 OverlayInteractFromHelpers2(OfxInteractHandle handle, OFX::ImageEffect* effect) 359 : OFX::OverlayInteract(handle) 360 , InteractHelper1(effect, this) 361 , InteractHelper2(effect, this) 362 { 363 } 364 365 private: draw(const DrawArgs & args)366 virtual bool draw(const DrawArgs &args) { 367 // draw all interacts, in reverse order 368 bool ret2 = InteractHelper2::draw(args); 369 bool ret1 = InteractHelper1::draw(args); 370 return ret1 || ret2; 371 } 372 penMotion(const PenArgs & args)373 virtual bool penMotion(const PenArgs &args) { 374 return InteractHelper1::penMotion(args) || InteractHelper2::penMotion(args); 375 } 376 penDown(const PenArgs & args)377 virtual bool penDown(const PenArgs &args) { 378 return InteractHelper1::penDown(args) || InteractHelper2::penDown(args); 379 } 380 penUp(const PenArgs & args)381 virtual bool penUp(const PenArgs &args) { 382 return InteractHelper1::penUp(args) || InteractHelper2::penUp(args); 383 } 384 keyDown(const OFX::KeyArgs & args)385 virtual bool keyDown(const OFX::KeyArgs &args) { 386 return InteractHelper1::keyDown(args) || InteractHelper2::keyDown(args); 387 } 388 keyUp(const OFX::KeyArgs & args)389 virtual bool keyUp(const OFX::KeyArgs &args) { 390 return InteractHelper1::keyUp(args) || InteractHelper2::keyUp(args); 391 } 392 keyRepeat(const KeyArgs & args)393 virtual bool keyRepeat(const KeyArgs &args) { 394 return InteractHelper1::keyRepeat(args) || InteractHelper2::keyRepeat(args); 395 } 396 gainFocus(const FocusArgs & args)397 virtual void gainFocus(const FocusArgs &args) { 398 InteractHelper1::gainFocus(args); InteractHelper2::gainFocus(args); 399 } 400 loseFocus(const FocusArgs & args)401 virtual void loseFocus(const FocusArgs &args) { 402 InteractHelper1::loseFocus(args); InteractHelper2::loseFocus(args); 403 } 404 }; 405 406 /** @brief an interact for an image effect overlay made from three InteractAbstract helper classes */ 407 template<class InteractHelper1, class InteractHelper2, class InteractHelper3> 408 class OverlayInteractFromHelpers3 : public OFX::OverlayInteract, private InteractHelper1, InteractHelper2, InteractHelper3 409 { 410 public: OverlayInteractFromHelpers3(OfxInteractHandle handle,OFX::ImageEffect * effect)411 OverlayInteractFromHelpers3(OfxInteractHandle handle, OFX::ImageEffect* effect) 412 : OFX::OverlayInteract(handle) 413 , InteractHelper1(effect, this) 414 , InteractHelper2(effect, this) 415 , InteractHelper3(effect, this) 416 { 417 } 418 419 private: draw(const DrawArgs & args)420 virtual bool draw(const DrawArgs &args) { 421 // draw all interacts, in reverse order 422 bool ret3 = InteractHelper3::draw(args); 423 bool ret2 = InteractHelper2::draw(args); 424 bool ret1 = InteractHelper1::draw(args); 425 return ret1 || ret2 || ret3; 426 } 427 penMotion(const PenArgs & args)428 virtual bool penMotion(const PenArgs &args) { 429 return InteractHelper1::penMotion(args) || InteractHelper2::penMotion(args) || InteractHelper3::penMotion(args); 430 } 431 penDown(const PenArgs & args)432 virtual bool penDown(const PenArgs &args) { 433 return InteractHelper1::penDown(args) || InteractHelper2::penDown(args) || InteractHelper3::penDown(args); 434 } 435 penUp(const PenArgs & args)436 virtual bool penUp(const PenArgs &args) { 437 return InteractHelper1::penUp(args) || InteractHelper2::penUp(args) || InteractHelper3::penUp(args); 438 } 439 keyDown(const OFX::KeyArgs & args)440 virtual bool keyDown(const OFX::KeyArgs &args) { 441 return InteractHelper1::keyDown(args) || InteractHelper2::keyDown(args) || InteractHelper3::keyDown(args); 442 } 443 keyUp(const OFX::KeyArgs & args)444 virtual bool keyUp(const OFX::KeyArgs &args) { 445 return InteractHelper1::keyUp(args) || InteractHelper2::keyUp(args) || InteractHelper3::keyUp(args); 446 } 447 keyRepeat(const KeyArgs & args)448 virtual bool keyRepeat(const KeyArgs &args) { 449 return InteractHelper1::keyRepeat(args) || InteractHelper2::keyRepeat(args) || InteractHelper3::keyRepeat(args); 450 } 451 gainFocus(const FocusArgs & args)452 virtual void gainFocus(const FocusArgs &args) { 453 InteractHelper1::gainFocus(args); InteractHelper2::gainFocus(args); InteractHelper3::gainFocus(args); 454 } 455 loseFocus(const FocusArgs & args)456 virtual void loseFocus(const FocusArgs &args) { 457 InteractHelper1::loseFocus(args); InteractHelper2::loseFocus(args);; InteractHelper3::loseFocus(args); 458 } 459 }; 460 461 class InteractDescriptor 462 { 463 public: InteractDescriptor()464 InteractDescriptor():_props(NULL) {} ~InteractDescriptor()465 virtual ~InteractDescriptor() {} setPropertySet(OFX::PropertySet * props)466 void setPropertySet(OFX::PropertySet* props){ _props = props; } 467 virtual Interact* createInstance(OfxInteractHandle handle, ImageEffect *effect) = 0; 468 bool getHasAlpha() const; 469 int getBitDepth() const; 470 #ifdef OFX_EXTENSIONS_NATRON 471 /** @brief Sets wether the interact uses an additional colour picking value in the inArgs of its actions. */ 472 void setColourPicking(bool useColourPicking); 473 #endif 474 virtual OfxPluginEntryPoint* getMainEntry() = 0; describe()475 virtual void describe() {} 476 protected: 477 OFX::PropertySet* _props; 478 }; 479 480 typedef InteractDescriptor EffectOverlayDescriptor; 481 482 class ParamInteractDescriptor : public InteractDescriptor 483 { 484 public: ParamInteractDescriptor()485 ParamInteractDescriptor():InteractDescriptor(){} ~ParamInteractDescriptor()486 virtual ~ParamInteractDescriptor() {} 487 void setInteractSizeAspect(double asp); 488 void setInteractMinimumSize(int x, int y); 489 void setInteractPreferredSize(int x, int y); setParamName(const std::string & pName)490 virtual void setParamName(const std::string& pName) { _paramName = pName; } 491 protected: 492 std::string _paramName; 493 }; 494 495 class ParamInteract : public Interact 496 { 497 public: 498 ParamInteract(OfxInteractHandle handle, ImageEffect* effect); ~ParamInteract()499 virtual ~ParamInteract() {} 500 double getInteractSizeAspect() const; 501 OfxPointI getInteractMinimumSize() const; 502 OfxPointI getInteractPreferredSize() const; 503 OfxPointI getInteractSize() const; 504 protected: 505 ImageEffect* _effect; 506 }; 507 508 namespace Private 509 { 510 OfxStatus interactMainEntry(const char *actionRaw, 511 const void *handleRaw, 512 OfxPropertySetHandle inArgsRaw, 513 OfxPropertySetHandle outArgsRaw, 514 InteractDescriptor& desc); 515 } 516 517 template<class DESC> 518 class InteractMainEntry 519 { 520 protected: overlayInteractMainEntry(const char * action,const void * handle,OfxPropertySetHandle in,OfxPropertySetHandle out)521 static OfxStatus overlayInteractMainEntry(const char *action, const void* handle, OfxPropertySetHandle in, OfxPropertySetHandle out) 522 { 523 static DESC desc; 524 return OFX::Private::interactMainEntry(action, handle, in, out, desc); 525 } 526 }; 527 528 template<class DESC, class INSTANCE> 529 class DefaultEffectOverlayDescriptor : public EffectOverlayDescriptor, public InteractMainEntry<DESC> 530 { 531 public: createInstance(OfxInteractHandle handle,ImageEffect * effect)532 Interact* createInstance(OfxInteractHandle handle, ImageEffect *effect) { return new INSTANCE(handle, effect); } getMainEntry()533 virtual OfxPluginEntryPoint* getMainEntry() { return InteractMainEntry<DESC>::overlayInteractMainEntry; } 534 }; 535 536 template<class DESC, class INSTANCE> 537 class DefaultParamInteractDescriptor : public ParamInteractDescriptor, public InteractMainEntry<DESC> 538 { 539 public: createInstance(OfxInteractHandle handle,ImageEffect * effect)540 Interact* createInstance(OfxInteractHandle handle, ImageEffect *effect) { return new INSTANCE(handle, effect, _paramNameStatic); } getMainEntry()541 virtual OfxPluginEntryPoint* getMainEntry() { return InteractMainEntry<DESC>::overlayInteractMainEntry; } setParamName(const std::string & pName)542 virtual void setParamName(const std::string& pName) { _paramNameStatic = pName; } 543 protected: 544 static std::string _paramNameStatic; 545 }; 546 547 template<class DESC, class INSTANCE> std::string OFX::DefaultParamInteractDescriptor<DESC, INSTANCE>::_paramNameStatic; 548 }; 549 550 551 #undef mDeclareProtectedAssignAndCC 552 553 #endif 554 555