1 /* ***** BEGIN LICENSE BLOCK *****
2 * This file is part of openfx-misc <https://github.com/devernay/openfx-misc>,
3 * Copyright (C) 2013-2018 INRIA
4 *
5 * openfx-misc is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * openfx-misc is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with openfx-misc. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
17 * ***** END LICENSE BLOCK ***** */
18
19 /*
20 * OFX NoOp plugin.
21 * Does nothing.
22 */
23
24 #include <sstream> // stringstream
25
26 #include "ofxsProcessing.H"
27 #include "ofxsMacros.h"
28 #include "ofxsCopier.h"
29 #include "ofxsCoords.h"
30 #include "ofxsGenerator.h" // for format-related parameters
31 #include "ofxsFormatResolution.h" // for format-related enums
32
33 #ifdef OFX_EXTENSIONS_NUKE
34 #include "nuke/fnOfxExtensions.h"
35 #endif
36
37 using namespace OFX;
38
39 OFXS_NAMESPACE_ANONYMOUS_ENTER
40
41 #define kPluginName "NoOpOFX"
42 #define kPluginGrouping "Other"
43 #define kPluginDescription "Copies the input to the ouput.\n" \
44 "This effect does not modify the actual content of the image, but can be used to modify the metadata associated with the clip (premultiplication, field order, format, pixel aspect ratio, frame rate).\n" \
45 "This plugin concatenates transforms."
46 #define kPluginIdentifier "net.sf.openfx.NoOpPlugin"
47
48 // History:
49 // Version 2.0: introduce setFormat, deprecate setPixelAspectRatio on Natron
50 #define kPluginVersionMajor 2 // Incrementing this number means that you have broken backwards compatibility of the plug-in.
51 #define kPluginVersionMinor 0 // Increment this when you have fixed a bug or made it faster.
52
53 #define kSupportsTiles 1
54 #define kSupportsMultiResolution 1
55 #define kSupportsRenderScale 1
56 #define kSupportsMultipleClipPARs true
57 #define kSupportsMultipleClipDepths true
58 #define kRenderThreadSafety eRenderFullySafe
59
60 #define kParamClipInfo "clipInfo"
61 #define kParamClipInfoLabel "Clip Info..."
62 #define kParamClipInfoHint "Display information about the inputs"
63
64 #define kParamForceCopy "forceCopy"
65 #define kParamForceCopyLabel "Force Copy"
66 #define kParamForceCopyHint "Force copy from input to output"
67
68 #define kParamSetPremult "setPremult"
69 #define kParamSetPremultLabel "Set Premultiplication"
70 #define kParamSetPremultHint "Set the premultiplication state of the output clip, without modifying the raw content. Use the Premult or UnPremult plu-gins to affect the content."
71
72 #define kParamOutputPremult "outputPremult"
73 #define kParamOutputPremultLabel "Output Premultiplication"
74 #define kParamOutputPremultHint "Premultiplication state of the output clip."
75
76 #define kParamSetFieldOrder "setFieldOrder"
77 #define kParamSetFieldOrderLabel "Set Field Order"
78 #define kParamSetFieldOrderHint "Set the field order state of the output clip, without modifying the raw content."
79
80 #define kParamOutputFieldOrder "outputFieldOrder"
81 #define kParamOutputFieldOrderLabel "Output Field Order"
82 #define kParamOutputFieldOrderHint "Field order state of the output clip."
83
84 #ifdef OFX_EXTENSIONS_NATRON
85 #define kParamSetFormat "setFormat"
86 #define kParamSetFormatLabel "Set Format"
87 #define kParamSetFormatHint "Set the format of the output clip, without modifying the raw content."
88 #endif
89
90 #define kParamSetPixelAspectRatio "setPixelAspectRatio"
91 #define kParamSetPixelAspectRatioLabel "Set Pixel Aspect Ratio"
92 #define kParamSetPixelAspectRatioHint "Set the pixel aspect ratio of the output clip, without modifying the raw content."
93
94 #define kParamOutputPixelAspectRatio "outputPixelAspectRatio"
95 #define kParamOutputPixelAspectRatioLabel "Output Pixel Aspect Ratio"
96 #define kParamOutputPixelAspectRatioHint "Pixel aspect ratio of the output clip."
97
98 #define kParamSetFrameRate "setFrameRate"
99 #define kParamSetFrameRateLabel "Set Frame Rate"
100 #define kParamSetFrameRateHint "Set the frame rate state of the output clip, without modifying the raw content."
101
102 #define kParamOutputFrameRate "outputFrameRate"
103 #define kParamOutputFrameRateLabel "Output Frame Rate"
104 #define kParamOutputFrameRateHint "Frame rate of the output clip."
105
106 // Some hosts (e.g. Resolve) may not support normalized defaults (setDefaultCoordinateSystem(eCoordinatesNormalised))
107 #define kParamDefaultsNormalised "defaultsNormalised"
108
109 static bool gHostSupportsDefaultCoordinateSystem = true; // for kParamDefaultsNormalised
110
111 ////////////////////////////////////////////////////////////////////////////////
112 /** @brief The plugin that does our work */
113 class NoOpPlugin
114 : public ImageEffect
115 {
116 public:
117 /** @brief ctor */
NoOpPlugin(OfxImageEffectHandle handle)118 NoOpPlugin(OfxImageEffectHandle handle)
119 : ImageEffect(handle)
120 , _dstClip(NULL)
121 , _srcClip(NULL)
122 , _forceCopy(NULL)
123 , _setPremult(NULL)
124 , _premult(NULL)
125 , _setFieldOrder(NULL)
126 , _fieldOrder(NULL)
127 #ifdef OFX_EXTENSIONS_NATRON
128 , _setFormat(NULL)
129 , _extent(NULL)
130 , _format(NULL)
131 , _formatSize(NULL)
132 , _formatPar(NULL)
133 , _btmLeft(NULL)
134 , _size(NULL)
135 , _recenter(NULL)
136 #endif
137 , _setPixelAspectRatio(NULL)
138 , _pixelAspectRatio(NULL)
139 , _setFrameRate(NULL)
140 , _frameRate(NULL)
141 {
142 _dstClip = fetchClip(kOfxImageEffectOutputClipName);
143 _srcClip = getContext() == eContextGenerator ? NULL : fetchClip(kOfxImageEffectSimpleSourceClipName);
144 _forceCopy = fetchBooleanParam(kParamForceCopy);
145 _setPremult = fetchBooleanParam(kParamSetPremult);
146 _premult = fetchChoiceParam(kParamOutputPremult);
147 assert(_forceCopy && _setPremult && _premult);
148
149 const ImageEffectHostDescription &gHostDescription = *getImageEffectHostDescription();
150 if (gHostDescription.supportsSetableFielding) {
151 _setFieldOrder = fetchBooleanParam(kParamSetFieldOrder);
152 _fieldOrder = fetchChoiceParam(kParamOutputFieldOrder);
153 assert(_setFieldOrder && _fieldOrder);
154 }
155 #ifdef OFX_EXTENSIONS_NATRON
156 if (gHostDescription.isNatron) {
157 _setFormat = fetchBooleanParam(kParamSetFormat);
158 _extent = fetchChoiceParam(kParamGeneratorExtent);
159 _format = fetchChoiceParam(kParamGeneratorFormat);
160 _formatSize = fetchInt2DParam(kParamGeneratorSize);
161 _formatPar = fetchDoubleParam(kParamGeneratorPAR);
162 _btmLeft = fetchDouble2DParam(kParamRectangleInteractBtmLeft);
163 _size = fetchDouble2DParam(kParamRectangleInteractSize);
164 _recenter = fetchPushButtonParam(kParamGeneratorCenter);
165 }
166 #endif
167 if (gHostDescription.supportsMultipleClipPARs) {
168 _setPixelAspectRatio = fetchBooleanParam(kParamSetPixelAspectRatio);
169 _pixelAspectRatio = fetchDoubleParam(kParamOutputPixelAspectRatio);
170 assert(_setPixelAspectRatio && _pixelAspectRatio);
171 }
172 if (gHostDescription.supportsSetableFrameRate) {
173 _setFrameRate = fetchBooleanParam(kParamSetFrameRate);
174 _frameRate = fetchDoubleParam(kParamOutputFrameRate);
175 assert(_setFrameRate && _frameRate);
176 }
177
178 #ifdef OFX_EXTENSIONS_NATRON
179 // honor kParamDefaultsNormalised
180 if ( paramExists(kParamDefaultsNormalised) ) {
181 // Some hosts (e.g. Resolve) may not support normalized defaults (setDefaultCoordinateSystem(eCoordinatesNormalised))
182 // handle these ourselves!
183 BooleanParam* param = fetchBooleanParam(kParamDefaultsNormalised);
184 assert(param);
185 bool normalised = param->getValue();
186 if (normalised) {
187 OfxPointD size = getProjectExtent();
188 OfxPointD origin = getProjectOffset();
189 OfxPointD p;
190 // we must denormalise all parameters for which setDefaultCoordinateSystem(eCoordinatesNormalised) couldn't be done
191 beginEditBlock(kParamDefaultsNormalised);
192 p = _btmLeft->getValue();
193 _btmLeft->setValue(p.x * size.x + origin.x, p.y * size.y + origin.y);
194 p = _size->getValue();
195 _size->setValue(p.x * size.x, p.y * size.y);
196 param->setValue(false);
197 endEditBlock();
198 }
199 }
200 #endif
201
202 // finally
203 syncPrivateData();
204 }
205
206 private:
207 // override the roi call
208 virtual void getRegionsOfInterest(const RegionsOfInterestArguments &args, RegionOfInterestSetter &rois) OVERRIDE FINAL;
209 virtual bool getRegionOfDefinition(const RegionOfDefinitionArguments &args, OfxRectD &rod) OVERRIDE FINAL;
210
211 /* Override the render */
212 virtual void render(const RenderArguments &args) OVERRIDE FINAL;
213 virtual bool isIdentity(const IsIdentityArguments &args, Clip * &identityClip, double &identityTime, int& view, std::string& plane) OVERRIDE FINAL;
214
215 /** @brief get the clip preferences */
216 virtual void getClipPreferences(ClipPreferencesSetter &clipPreferences) OVERRIDE FINAL;
217
218 #ifdef OFX_EXTENSIONS_NUKE
219 /** @brief recover a transform matrix from an effect */
220 virtual bool getTransform(const TransformArguments & args, Clip * &transformClip, double transformMatrix[9]) OVERRIDE FINAL;
221 #endif
222
223 virtual void changedParam(const InstanceChangedArgs &args, const std::string ¶mName) OVERRIDE FINAL;
224
225 /** @brief The sync private data action, called when the effect needs to sync any private data to persistent parameters */
syncPrivateData(void)226 virtual void syncPrivateData(void) OVERRIDE FINAL
227 {
228 updateVisibility();
229 }
230
updateVisibility()231 void updateVisibility()
232 {
233 const ImageEffectHostDescription &gHostDescription = *getImageEffectHostDescription();
234
235 _premult->setEnabled( _setPremult->getValue() );
236 if (gHostDescription.supportsSetableFielding) {
237 _fieldOrder->setEnabled( _setFieldOrder->getValue() );
238 }
239 #ifdef OFX_EXTENSIONS_NATRON
240 if (gHostDescription.isNatron) {
241 GeneratorExtentEnum extent = (GeneratorExtentEnum)_extent->getValue();
242 bool hasFormat = (extent == eGeneratorExtentFormat);
243 bool hasSize = (extent == eGeneratorExtentSize);
244
245 _format->setIsSecret(!hasFormat);
246 _size->setIsSecret(!hasSize);
247 _recenter->setIsSecret(!hasSize);
248 _btmLeft->setIsSecret(!hasSize);
249
250 bool setFormat = _setFormat->getValue();
251 _extent->setEnabled(setFormat);
252 _format->setEnabled(setFormat);
253 _size->setEnabled(setFormat);
254 _recenter->setEnabled(setFormat);
255 _btmLeft->setEnabled(setFormat);
256 }
257 #endif
258 if (gHostDescription.supportsMultipleClipPARs) {
259 _pixelAspectRatio->setEnabled( _setPixelAspectRatio->getValue() );
260 }
261 if (gHostDescription.supportsSetableFrameRate) {
262 _frameRate->setEnabled( _setFrameRate->getValue() );
263 }
264 }
265
266 private:
267 // do not need to delete these, the ImageEffect is managing them for us
268 Clip *_dstClip;
269 Clip *_srcClip;
270 BooleanParam *_forceCopy;
271 BooleanParam *_setPremult;
272 ChoiceParam *_premult;
273 BooleanParam *_setFieldOrder;
274 ChoiceParam *_fieldOrder;
275 #ifdef OFX_EXTENSIONS_NATRON
276 BooleanParam *_setFormat;
277 ChoiceParam* _extent;
278 ChoiceParam* _format;
279 Int2DParam* _formatSize;
280 DoubleParam* _formatPar;
281 Double2DParam* _btmLeft;
282 Double2DParam* _size;
283 PushButtonParam *_recenter;
284 #endif
285 BooleanParam *_setPixelAspectRatio;
286 DoubleParam *_pixelAspectRatio;
287 BooleanParam *_setFrameRate;
288 DoubleParam *_frameRate;
289 };
290
291
292 ////////////////////////////////////////////////////////////////////////////////
293 /** @brief render for the filter */
294
295 ////////////////////////////////////////////////////////////////////////////////
296 // basic plugin render function, just a skelington to instantiate templates from
297
298 // override the roi call
299 // Required if the plugin requires a region from the inputs which is different from the rendered region of the output.
300 // (this is the case here)
301 void
getRegionsOfInterest(const RegionsOfInterestArguments & args,RegionOfInterestSetter & rois)302 NoOpPlugin::getRegionsOfInterest(const RegionsOfInterestArguments &args,
303 RegionOfInterestSetter &rois)
304 {
305 if (!_srcClip || !_srcClip->isConnected()) {
306 return;
307 }
308 if (!_setPixelAspectRatio) {
309 return;
310 }
311 bool setPixelAspectRatio;
312 _setPixelAspectRatio->getValueAtTime(args.time, setPixelAspectRatio);
313 if (!setPixelAspectRatio) {
314 return;
315 }
316 double srcPAR = _srcClip->getPixelAspectRatio();
317 double pixelAspectRatio = 1.;
318 _pixelAspectRatio->getValueAtTime(args.time, pixelAspectRatio);
319 if ( (srcPAR <= 0) || (pixelAspectRatio <= 0) ) {
320 return;
321 }
322
323 OfxRectD srcRoI = args.regionOfInterest;
324 srcRoI.x1 *= srcPAR / pixelAspectRatio;
325 srcRoI.x2 *= srcPAR / pixelAspectRatio;
326
327 rois.setRegionOfInterest(*_srcClip, srcRoI);
328 }
329
330 bool
getRegionOfDefinition(const RegionOfDefinitionArguments & args,OfxRectD & rod)331 NoOpPlugin::getRegionOfDefinition(const RegionOfDefinitionArguments &args,
332 OfxRectD &rod)
333 {
334 if (!_srcClip || !_srcClip->isConnected()) {
335 return false;
336 }
337 if (!_setPixelAspectRatio) {
338 return false;
339 }
340 bool setPixelAspectRatio;
341 _setPixelAspectRatio->getValueAtTime(args.time, setPixelAspectRatio);
342 if (!setPixelAspectRatio) {
343 return false;
344 }
345 double srcPAR = _srcClip->getPixelAspectRatio();
346 double pixelAspectRatio = 1.;
347 if (_pixelAspectRatio) {
348 _pixelAspectRatio->getValueAtTime(args.time, pixelAspectRatio);
349 }
350 #ifdef OFX_EXTENSIONS_NATRON
351 if (_formatPar) {
352 _formatPar->getValueAtTime(args.time, pixelAspectRatio);
353 }
354 #endif
355 if ( (srcPAR <= 0) || (pixelAspectRatio <= 0) ) {
356 return false;
357 }
358
359 const OfxRectD srcRoD = _srcClip->getRegionOfDefinition(args.time);
360 if ( Coords::rectIsEmpty(srcRoD) ) {
361 return false;
362 }
363 rod = srcRoD;
364 rod.x1 *= pixelAspectRatio / srcPAR;
365 rod.x2 *= pixelAspectRatio / srcPAR;
366
367 return true;
368 }
369
370 // the overridden render function
371 void
render(const RenderArguments & args)372 NoOpPlugin::render(const RenderArguments &args)
373 {
374 const double time = args.time;
375 bool forceCopy;
376
377 _forceCopy->getValueAtTime(time, forceCopy);
378
379 #ifdef DEBUG
380 if (!forceCopy) {
381 setPersistentMessage(Message::eMessageError, "", "OFX Host should not render");
382 throwSuiteStatusException(kOfxStatFailed);
383 }
384 #endif
385
386 assert( kSupportsMultipleClipPARs || !_srcClip || _srcClip->getPixelAspectRatio() == _dstClip->getPixelAspectRatio() );
387 assert( kSupportsMultipleClipDepths || !_srcClip || _srcClip->getPixelDepth() == _dstClip->getPixelDepth() );
388 // do the rendering
389 auto_ptr<Image> dst( _dstClip->fetchImage(args.time) );
390 if ( !dst.get() ) {
391 throwSuiteStatusException(kOfxStatFailed);
392 }
393 if ( (dst->getRenderScale().x != args.renderScale.x) ||
394 ( dst->getRenderScale().y != args.renderScale.y) ||
395 ( ( dst->getField() != eFieldNone) /* for DaVinci Resolve */ && ( dst->getField() != args.fieldToRender) ) ) {
396 setPersistentMessage(Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
397 throwSuiteStatusException(kOfxStatFailed);
398 }
399 BitDepthEnum dstBitDepth = dst->getPixelDepth();
400 PixelComponentEnum dstComponents = dst->getPixelComponents();
401 auto_ptr<const Image> src( ( _srcClip && _srcClip->isConnected() ) ?
402 _srcClip->fetchImage(args.time) : 0 );
403 if ( src.get() ) {
404 if ( (src->getRenderScale().x != args.renderScale.x) ||
405 ( src->getRenderScale().y != args.renderScale.y) ||
406 ( ( src->getField() != eFieldNone) /* for DaVinci Resolve */ && ( src->getField() != args.fieldToRender) ) ) {
407 setPersistentMessage(Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
408 throwSuiteStatusException(kOfxStatFailed);
409 }
410 BitDepthEnum srcBitDepth = src->getPixelDepth();
411 PixelComponentEnum srcComponents = src->getPixelComponents();
412 if ( (srcBitDepth != dstBitDepth) || (srcComponents != dstComponents) ) {
413 throwSuiteStatusException(kOfxStatErrImageFormat);
414 }
415 }
416 copyPixels( *this, args.renderWindow, src.get(), dst.get() );
417 }
418
419 bool
isIdentity(const IsIdentityArguments & args,Clip * & identityClip,double &,int &,std::string &)420 NoOpPlugin::isIdentity(const IsIdentityArguments &args,
421 Clip * &identityClip,
422 double & /*identityTime*/
423 , int& /*view*/, std::string& /*plane*/)
424 {
425 const double time = args.time;
426 bool forceCopy;
427
428 _forceCopy->getValueAtTime(time, forceCopy);
429
430 if (!forceCopy) {
431 identityClip = _srcClip;
432
433 return true;
434 } else {
435 return false;
436 }
437 }
438
439 #ifdef OFX_EXTENSIONS_NUKE
440 // overridden getTransform
441 bool
getTransform(const TransformArguments & args,Clip * & transformClip,double transformMatrix[9])442 NoOpPlugin::getTransform(const TransformArguments &args,
443 Clip * &transformClip,
444 double transformMatrix[9])
445 {
446 const double time = args.time;
447 bool forceCopy;
448
449 _forceCopy->getValueAtTime(time, forceCopy);
450 if (forceCopy) {
451 return false;
452 }
453 transformClip = _srcClip;
454 transformMatrix[0] = 1.;
455 transformMatrix[1] = 0.;
456 transformMatrix[2] = 0.;
457 transformMatrix[3] = 0.;
458 transformMatrix[4] = 1.;
459 transformMatrix[5] = 0.;
460 transformMatrix[6] = 0.;
461 transformMatrix[7] = 0.;
462 transformMatrix[8] = 1.;
463
464 return true;
465 }
466
467 #endif
468
469
470 static const char*
bitDepthString(BitDepthEnum bitDepth)471 bitDepthString(BitDepthEnum bitDepth)
472 {
473 switch (bitDepth) {
474 case eBitDepthUByte:
475
476 return "8u";
477 case eBitDepthUShort:
478
479 return "16u";
480 case eBitDepthHalf:
481
482 return "16f";
483 case eBitDepthFloat:
484
485 return "32f";
486 case eBitDepthCustom:
487
488 return "x";
489 case eBitDepthNone:
490
491 return "0";
492 #ifdef OFX_EXTENSIONS_VEGAS
493 case eBitDepthUByteBGRA:
494
495 return "8uBGRA";
496 case eBitDepthUShortBGRA:
497
498 return "16uBGRA";
499 case eBitDepthFloatBGRA:
500
501 return "32fBGRA";
502 #endif
503 default:
504
505 return "[unknown bit depth]";
506 }
507 }
508
509 static std::string
pixelComponentString(const std::string & p)510 pixelComponentString(const std::string& p)
511 {
512 const std::string prefix = "OfxImageComponent";
513
514 std::string s = p;
515
516 return s.replace(s.find(prefix), prefix.length(), "");
517 }
518
519 static const char*
premultString(PreMultiplicationEnum e)520 premultString(PreMultiplicationEnum e)
521 {
522 switch (e) {
523 case eImageOpaque:
524
525 return "Opaque";
526 case eImagePreMultiplied:
527
528 return "PreMultiplied";
529 case eImageUnPreMultiplied:
530
531 return "UnPreMultiplied";
532 default:
533
534 return "[unknown premult]";
535 }
536 }
537
538 #ifdef OFX_EXTENSIONS_VEGAS
539 static const char*
pixelOrderString(PixelOrderEnum e)540 pixelOrderString(PixelOrderEnum e)
541 {
542 switch (e) {
543 case ePixelOrderRGBA:
544
545 return "RGBA";
546 case ePixelOrderBGRA:
547
548 return "BGRA";
549 default:
550
551 return "[unknown pixel order]";
552 }
553 }
554
555 #endif
556
557 static const char*
fieldOrderString(FieldEnum e)558 fieldOrderString(FieldEnum e)
559 {
560 switch (e) {
561 case eFieldNone:
562
563 return "None";
564 case eFieldBoth:
565
566 return "Both";
567 case eFieldLower:
568
569 return "Lower";
570 case eFieldUpper:
571
572 return "Upper";
573 case eFieldSingle:
574
575 return "Single";
576 case eFieldDoubled:
577
578 return "Doubled";
579 default:
580
581 return "[unknown field order]";
582 }
583 }
584
585 void
changedParam(const InstanceChangedArgs & args,const std::string & paramName)586 NoOpPlugin::changedParam(const InstanceChangedArgs &args,
587 const std::string ¶mName)
588 {
589 if (paramName == kParamSetPremult) {
590 updateVisibility();
591 } else if (paramName == kParamSetFieldOrder) {
592 updateVisibility();
593 } else if (paramName == kParamSetFieldOrder) {
594 updateVisibility();
595 #ifdef OFX_EXTENSIONS_NATRON
596 } else if (paramName == kParamSetFormat) {
597 updateVisibility();
598 } else if (paramName == kParamGeneratorExtent) {
599 updateVisibility();
600 } else if (paramName == kParamGeneratorFormat) {
601 //the host does not handle the format itself, do it ourselves
602 EParamFormat format = (EParamFormat)_format->getValue();
603 int w = 0, h = 0;
604 double par = -1;
605 getFormatResolution(format, &w, &h, &par);
606 assert(par != -1);
607 _formatPar->setValue(par);
608 _formatSize->setValue(w, h);
609 } else if (paramName == kParamGeneratorCenter) {
610 Clip* srcClip = _srcClip;
611 OfxRectD srcRoD;
612 if ( srcClip && srcClip->isConnected() ) {
613 srcRoD = srcClip->getRegionOfDefinition(args.time);
614 } else {
615 OfxPointD siz = getProjectSize();
616 OfxPointD off = getProjectOffset();
617 srcRoD.x1 = off.x;
618 srcRoD.x2 = off.x + siz.x;
619 srcRoD.y1 = off.y;
620 srcRoD.y2 = off.y + siz.y;
621 }
622 OfxPointD center;
623 center.x = (srcRoD.x2 + srcRoD.x1) / 2.;
624 center.y = (srcRoD.y2 + srcRoD.y1) / 2.;
625
626 OfxRectD rectangle;
627 _size->getValue(rectangle.x2, rectangle.y2);
628 _btmLeft->getValue(rectangle.x1, rectangle.y1);
629 rectangle.x2 += rectangle.x1;
630 rectangle.y2 += rectangle.y1;
631
632 OfxRectD newRectangle;
633 newRectangle.x1 = center.x - (rectangle.x2 - rectangle.x1) / 2.;
634 newRectangle.y1 = center.y - (rectangle.y2 - rectangle.y1) / 2.;
635 newRectangle.x2 = newRectangle.x1 + (rectangle.x2 - rectangle.x1);
636 newRectangle.y2 = newRectangle.y1 + (rectangle.y2 - rectangle.y1);
637
638 _size->setValue(newRectangle.x2 - newRectangle.x1, newRectangle.y2 - newRectangle.y1);
639 _btmLeft->setValue(newRectangle.x1, newRectangle.y1);
640 #endif
641 } else if (paramName == kParamSetPixelAspectRatio) {
642 updateVisibility();
643 } else if (paramName == kParamSetFrameRate) {
644 updateVisibility();
645 } else if (paramName == kParamClipInfo) {
646 std::ostringstream oss;
647 oss << "Clip Info:\n\n";
648 oss << "Input: ";
649 if (!_srcClip) {
650 oss << "N/A";
651 } else {
652 Clip &c = *_srcClip;
653 oss << pixelComponentString( c.getPixelComponentsProperty() );
654 oss << bitDepthString( c.getPixelDepth() );
655 oss << " (unmapped: ";
656 oss << pixelComponentString( c.getUnmappedPixelComponentsProperty() );
657 oss << bitDepthString( c.getUnmappedPixelDepth() );
658 oss << ")\npremultiplication: ";
659 oss << premultString( c.getPreMultiplication() );
660 #ifdef OFX_EXTENSIONS_VEGAS
661 oss << "\npixel order: ";
662 oss << pixelOrderString( c.getPixelOrder() );
663 #endif
664 oss << "\nfield order: ";
665 oss << fieldOrderString( c.getFieldOrder() );
666 oss << "\n";
667 oss << (c.isConnected() ? "connected" : "not connected");
668 oss << "\n";
669 oss << (c.hasContinuousSamples() ? "continuous samples" : "discontinuous samples");
670 #ifdef OFX_EXTENSIONS_NATRON
671 oss << "\nformat: ";
672 OfxRectI format;
673 c.getFormat(format);
674 oss << format.x2 - format.x1 << 'x' << format.y2 - format.y1;
675 if ( (format.x1 != 0) && (format.y1 != 0) ) {
676 if (format.x1 < 0) {
677 oss << format.x1;
678 } else {
679 oss << '+' << format.x1;
680 }
681 if (format.y1 < 0) {
682 oss << format.y1;
683 } else {
684 oss << '+' << format.y1;
685 }
686 }
687 #endif
688 oss << "\npixel aspect ratio: ";
689 oss << c.getPixelAspectRatio();
690 oss << "\nframe rate: ";
691 oss << c.getFrameRate();
692 oss << " (unmapped: ";
693 oss << c.getUnmappedFrameRate();
694 oss << ")";
695 OfxRangeD range = c.getFrameRange();
696 oss << "\nframe range: ";
697 oss << range.min << "..." << range.max;
698 oss << " (unmapped: ";
699 range = c.getUnmappedFrameRange();
700 oss << range.min << "..." << range.max;
701 oss << ")";
702 oss << "\nregion of definition: ";
703 OfxRectD rod = c.getRegionOfDefinition(args.time);
704 oss << rod.x1 << ' ' << rod.y1 << ' ' << rod.x2 << ' ' << rod.y2;
705 }
706 oss << "\n\n";
707 oss << "Output: ";
708 if (!_dstClip) {
709 oss << "N/A";
710 } else {
711 Clip &c = *_dstClip;
712 oss << pixelComponentString( c.getPixelComponentsProperty() );
713 oss << bitDepthString( c.getPixelDepth() );
714 oss << " (unmapped: ";
715 oss << pixelComponentString( c.getUnmappedPixelComponentsProperty() );
716 oss << bitDepthString( c.getUnmappedPixelDepth() );
717 oss << ")\npremultiplication: ";
718 oss << premultString( c.getPreMultiplication() );
719 #ifdef OFX_EXTENSIONS_VEGAS
720 oss << "\npixel order: ";
721 oss << pixelOrderString( c.getPixelOrder() );
722 #endif
723 oss << "\nfield order: ";
724 oss << fieldOrderString( c.getFieldOrder() );
725 oss << "\n";
726 oss << (c.isConnected() ? "connected" : "not connected");
727 oss << "\n";
728 oss << (c.hasContinuousSamples() ? "continuous samples" : "discontinuous samples");
729 #ifdef OFX_EXTENSIONS_NATRON
730 oss << "\nformat: ";
731 OfxRectI format;
732 c.getFormat(format);
733 oss << format.x2 - format.x1 << 'x' << format.y2 - format.y1;
734 if ( (format.x1 != 0) && (format.y1 != 0) ) {
735 if (format.x1 < 0) {
736 oss << format.x1;
737 } else {
738 oss << '+' << format.x1;
739 }
740 if (format.y1 < 0) {
741 oss << format.y1;
742 } else {
743 oss << '+' << format.y1;
744 }
745 }
746 #endif
747 oss << "\npixel aspect ratio: ";
748 oss << c.getPixelAspectRatio();
749 oss << "\nframe rate: ";
750 oss << c.getFrameRate();
751 oss << " (unmapped: ";
752 oss << c.getUnmappedFrameRate();
753 oss << ")";
754 OfxRangeD range = c.getFrameRange();
755 oss << "\nframe range: ";
756 oss << range.min << "..." << range.max;
757 oss << " (unmapped: ";
758 range = c.getUnmappedFrameRange();
759 oss << range.min << "..." << range.max;
760 oss << ")";
761 oss << "\nregion of definition: ";
762 OfxRectD rod = c.getRegionOfDefinition(args.time);
763 oss << rod.x1 << ' ' << rod.y1 << ' ' << rod.x2 << ' ' << rod.y2;
764 }
765 oss << "\n\n";
766 oss << "time: " << args.time << ", renderscale: " << args.renderScale.x << 'x' << args.renderScale.y << '\n';
767
768 sendMessage( Message::eMessageMessage, "", oss.str() );
769 }
770 } // NoOpPlugin::changedParam
771
772 /* Override the clip preferences */
773 void
getClipPreferences(ClipPreferencesSetter & clipPreferences)774 NoOpPlugin::getClipPreferences(ClipPreferencesSetter &clipPreferences)
775 {
776 // set the premultiplication of _dstClip
777 bool setPremult = _setPremult->getValue();
778
779 if (setPremult) {
780 PreMultiplicationEnum premult = (PreMultiplicationEnum)_premult->getValue();
781
782 clipPreferences.setOutputPremultiplication(premult);
783 }
784 if (_setFieldOrder) {
785 // set the field order of _dstClip
786 bool setFieldOrder = _setFieldOrder->getValue();
787 if (setFieldOrder) {
788 FieldEnum fieldOrder = (FieldEnum)_fieldOrder->getValue();
789
790 clipPreferences.setOutputFielding(fieldOrder);
791 }
792 }
793 #ifdef OFX_EXTENSIONS_NATRON
794 if (_setFormat) {
795 bool setFormat = _setFormat->getValue();
796 if (setFormat) {
797 GeneratorExtentEnum extent = (GeneratorExtentEnum)_extent->getValue();
798
799 switch (extent) {
800 case eGeneratorExtentFormat: {
801 int w, h;
802 _formatSize->getValue(w, h);
803 double par = _formatPar->getValue();
804 OfxRectI pixelFormat;
805 pixelFormat.x1 = pixelFormat.y1 = 0;
806 pixelFormat.x2 = w;
807 pixelFormat.y2 = h;
808 clipPreferences.setOutputFormat(pixelFormat);
809 clipPreferences.setPixelAspectRatio(*_dstClip, par);
810 break;
811 }
812 case eGeneratorExtentSize: {
813 OfxRectD rod;
814 _size->getValue(rod.x2, rod.y2);
815 _btmLeft->getValue(rod.x1, rod.y1);
816 rod.x2 += rod.x1;
817 rod.y2 += rod.y1;
818 double par = _srcClip->getPixelAspectRatio();
819 OfxPointD renderScale = {1., 1.};
820 OfxRectI pixelFormat;
821 Coords::toPixelNearest(rod, renderScale, par, &pixelFormat);
822 clipPreferences.setOutputFormat(pixelFormat);
823 //clipPreferences.setPixelAspectRatio(*_dstClip, par); // should be the default
824 break;
825 }
826 case eGeneratorExtentProject: {
827 OfxRectD rod;
828 OfxPointD siz = getProjectSize();
829 OfxPointD off = getProjectOffset();
830 rod.x1 = off.x;
831 rod.x2 = off.x + siz.x;
832 rod.y1 = off.y;
833 rod.y2 = off.y + siz.y;
834 double par = getProjectPixelAspectRatio();
835 OfxPointD renderScale = {1., 1.};
836 OfxRectI pixelFormat;
837 Coords::toPixelNearest(rod, renderScale, par, &pixelFormat);
838 clipPreferences.setOutputFormat(pixelFormat);
839 clipPreferences.setPixelAspectRatio(*_dstClip, par);
840 break;
841 }
842 case eGeneratorExtentDefault:
843 break;
844 }
845 }
846 }
847 #endif // ifdef OFX_EXTENSIONS_NATRON
848 if (_setPixelAspectRatio) {
849 bool setPixelAspectRatio = _setPixelAspectRatio->getValue();
850 if (setPixelAspectRatio) {
851 double pixelAspectRatio = _pixelAspectRatio->getValue();
852 clipPreferences.setPixelAspectRatio(*_dstClip, pixelAspectRatio);
853 }
854 }
855 if (_setFrameRate) {
856 bool setFrameRate = _setFrameRate->getValue();
857 if (setFrameRate) {
858 double frameRate = _frameRate->getValue();
859 clipPreferences.setOutputFrameRate(frameRate);
860 }
861 }
862 } // NoOpPlugin::getClipPreferences
863
864 mDeclarePluginFactory(NoOpPluginFactory, {ofxsThreadSuiteCheck();}, {});
865 void
describe(ImageEffectDescriptor & desc)866 NoOpPluginFactory::describe(ImageEffectDescriptor &desc)
867 {
868 // basic labels
869 desc.setLabel(kPluginName);
870 desc.setPluginGrouping(kPluginGrouping);
871 desc.setPluginDescription(kPluginDescription);
872
873 // add the supported contexts, only filter at the moment
874 desc.addSupportedContext(eContextFilter);
875
876 // add supported pixel depths
877 desc.addSupportedBitDepth(eBitDepthNone);
878 desc.addSupportedBitDepth(eBitDepthUByte);
879 desc.addSupportedBitDepth(eBitDepthUShort);
880 desc.addSupportedBitDepth(eBitDepthHalf);
881 desc.addSupportedBitDepth(eBitDepthFloat);
882 desc.addSupportedBitDepth(eBitDepthCustom);
883 #ifdef OFX_EXTENSIONS_VEGAS
884 desc.addSupportedBitDepth(eBitDepthUByteBGRA);
885 desc.addSupportedBitDepth(eBitDepthUShortBGRA);
886 desc.addSupportedBitDepth(eBitDepthFloatBGRA);
887 #endif
888
889 // set a few flags
890 desc.setSingleInstance(false);
891 desc.setHostFrameThreading(false);
892 desc.setSupportsMultiResolution(kSupportsMultiResolution);
893 desc.setSupportsTiles(kSupportsTiles);
894 desc.setTemporalClipAccess(false);
895 desc.setRenderTwiceAlways(false);
896 desc.setSupportsMultipleClipPARs(kSupportsMultipleClipPARs);
897 desc.setSupportsMultipleClipDepths(kSupportsMultipleClipDepths);
898 desc.setRenderThreadSafety(kRenderThreadSafety);
899 #ifdef OFX_EXTENSIONS_NUKE
900 // Enable transform by the host.
901 // It is only possible for transforms which can be represented as a 3x3 matrix.
902 desc.setCanTransform(true);
903 // ask the host to render all planes
904 desc.setPassThroughForNotProcessedPlanes(ePassThroughLevelRenderAllRequestedPlanes);
905 #endif
906 #ifdef OFX_EXTENSIONS_NATRON
907 desc.setChannelSelector(ePixelComponentNone);
908 #endif
909 desc.setOverlayInteractDescriptor(new GeneratorOverlayDescriptor);
910 }
911
912 void
describeInContext(ImageEffectDescriptor & desc,ContextEnum)913 NoOpPluginFactory::describeInContext(ImageEffectDescriptor &desc,
914 ContextEnum /*context*/)
915 {
916 // Source clip only in the filter context
917 // create the mandated source clip
918 ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
919
920 srcClip->addSupportedComponent(ePixelComponentNone);
921 srcClip->addSupportedComponent(ePixelComponentRGBA);
922 srcClip->addSupportedComponent(ePixelComponentRGB);
923 srcClip->addSupportedComponent(ePixelComponentAlpha);
924 #ifdef OFX_EXTENSIONS_NATRON
925 srcClip->addSupportedComponent(ePixelComponentXY);
926 #endif
927 #ifdef OFX_EXTENSIONS_NUKE
928 srcClip->setCanTransform(true);
929 #endif
930 srcClip->setTemporalClipAccess(false);
931 srcClip->setSupportsTiles(kSupportsTiles);
932 srcClip->setIsMask(false);
933
934 // create the mandated output clip
935 ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
936 dstClip->addSupportedComponent(ePixelComponentNone);
937 dstClip->addSupportedComponent(ePixelComponentRGBA);
938 dstClip->addSupportedComponent(ePixelComponentRGB);
939 dstClip->addSupportedComponent(ePixelComponentAlpha);
940 #ifdef OFX_EXTENSIONS_NATRON
941 dstClip->addSupportedComponent(ePixelComponentXY);
942 #endif
943 dstClip->setSupportsTiles(kSupportsTiles);
944
945 // make some pages and to things in
946 PageParamDescriptor *page = desc.definePageParam("Controls");
947
948 // forceCopy
949 {
950 BooleanParamDescriptor *param = desc.defineBooleanParam(kParamForceCopy);
951 param->setLabel(kParamForceCopyLabel);
952 param->setHint(kParamForceCopyHint);
953 param->setDefault(false);
954 param->setAnimates(false);
955 if (page) {
956 page->addChild(*param);
957 }
958 }
959
960 //// setPremult
961 {
962 BooleanParamDescriptor* param = desc.defineBooleanParam(kParamSetPremult);
963 param->setLabel(kParamSetPremultLabel);
964 param->setHint(kParamSetPremultHint);
965 param->setDefault(false);
966 param->setAnimates(false);
967 desc.addClipPreferencesSlaveParam(*param);
968 if (page) {
969 page->addChild(*param);
970 }
971 }
972
973 //// premult
974 {
975 ChoiceParamDescriptor* param = desc.defineChoiceParam(kParamOutputPremult);
976 param->setLabel(kParamOutputPremultLabel);
977 param->setHint(kParamOutputPremultHint);
978 assert(param->getNOptions() == eImageOpaque);
979 param->appendOption( premultString(eImageOpaque) );
980 assert(param->getNOptions() == eImagePreMultiplied);
981 param->appendOption( premultString(eImagePreMultiplied) );
982 assert(param->getNOptions() == eImageUnPreMultiplied);
983 param->appendOption( premultString(eImageUnPreMultiplied) );
984 param->setDefault(eImagePreMultiplied); // images should be premultiplied in a compositing context
985 param->setAnimates(false);
986 desc.addClipPreferencesSlaveParam(*param);
987 if (page) {
988 page->addChild(*param);
989 }
990 }
991 const ImageEffectHostDescription &gHostDescription = *getImageEffectHostDescription();
992
993 if (gHostDescription.supportsSetableFielding) {
994 //// setFieldOrder
995 {
996 BooleanParamDescriptor* param = desc.defineBooleanParam(kParamSetFieldOrder);
997 param->setLabel(kParamSetFieldOrderLabel);
998 param->setHint(kParamSetFieldOrderHint);
999 param->setDefault(false);
1000 param->setAnimates(false);
1001 desc.addClipPreferencesSlaveParam(*param);
1002 if (page) {
1003 page->addChild(*param);
1004 }
1005 }
1006
1007 //// fieldOrder
1008 {
1009 ChoiceParamDescriptor* param = desc.defineChoiceParam(kParamOutputFieldOrder);
1010 param->setLabel(kParamOutputFieldOrderLabel);
1011 param->setHint(kParamOutputFieldOrderHint);
1012 assert(param->getNOptions() == eFieldNone);
1013 param->appendOption( fieldOrderString(eFieldNone) );
1014 assert(param->getNOptions() == eFieldBoth);
1015 param->appendOption( fieldOrderString(eFieldBoth) );
1016 assert(param->getNOptions() == eFieldLower);
1017 param->appendOption( fieldOrderString(eFieldLower) );
1018 assert(param->getNOptions() == eFieldUpper);
1019 param->appendOption( fieldOrderString(eFieldUpper) );
1020 assert(param->getNOptions() == eFieldSingle);
1021 param->appendOption( fieldOrderString(eFieldSingle) );
1022 assert(param->getNOptions() == eFieldDoubled);
1023 param->appendOption( fieldOrderString(eFieldDoubled) );
1024 param->setDefault(eFieldNone);
1025 param->setAnimates(false);
1026 desc.addClipPreferencesSlaveParam(*param);
1027 if (page) {
1028 page->addChild(*param);
1029 }
1030 }
1031 }
1032
1033 #ifdef OFX_EXTENSIONS_NATRON
1034 if (gHostDescription.isNatron) {
1035 //// setFormat
1036 {
1037 BooleanParamDescriptor* param = desc.defineBooleanParam(kParamSetFormat);
1038 param->setLabel(kParamSetFormatLabel);
1039 param->setHint(kParamSetFormatHint);
1040 param->setDefault(false);
1041 param->setAnimates(false);
1042 desc.addClipPreferencesSlaveParam(*param);
1043 if (page) {
1044 page->addChild(*param);
1045 }
1046 }
1047 // extent
1048 {
1049 ChoiceParamDescriptor* param = desc.defineChoiceParam(kParamGeneratorExtent);
1050 param->setLabel(kParamGeneratorExtentLabel);
1051 param->setHint(kParamGeneratorExtentHint);
1052 assert(param->getNOptions() == eGeneratorExtentFormat);
1053 param->appendOption(kParamGeneratorExtentOptionFormat);
1054 assert(param->getNOptions() == eGeneratorExtentSize);
1055 param->appendOption(kParamGeneratorExtentOptionSize);
1056 assert(param->getNOptions() == eGeneratorExtentProject);
1057 param->appendOption(kParamGeneratorExtentOptionProject);
1058 //assert(param->getNOptions() == eGeneratorExtentDefault);
1059 //param->appendOption(kParamGeneratorExtentOptionDefault);
1060 param->setDefault(eGeneratorExtentFormat);
1061 param->setLayoutHint(eLayoutHintNoNewLine, 1);
1062 param->setAnimates(false);
1063 desc.addClipPreferencesSlaveParam(*param);
1064 if (page) {
1065 page->addChild(*param);
1066 }
1067 }
1068
1069 // recenter
1070 {
1071 PushButtonParamDescriptor* param = desc.definePushButtonParam(kParamGeneratorCenter);
1072 param->setLabel(kParamGeneratorCenterLabel);
1073 param->setHint(kParamGeneratorCenterHint);
1074 param->setLayoutHint(eLayoutHintNoNewLine, 1);
1075 if (page) {
1076 page->addChild(*param);
1077 }
1078 }
1079
1080 // format
1081 {
1082 ChoiceParamDescriptor* param = desc.defineChoiceParam(kParamGeneratorFormat);
1083 param->setLabel(kParamGeneratorFormatLabel);
1084 assert(param->getNOptions() == eParamFormatPCVideo);
1085 param->appendOption(kParamFormatPCVideoLabel, "", kParamFormatPCVideo);
1086 assert(param->getNOptions() == eParamFormatNTSC);
1087 param->appendOption(kParamFormatNTSCLabel, "", kParamFormatNTSC);
1088 assert(param->getNOptions() == eParamFormatPAL);
1089 param->appendOption(kParamFormatPALLabel, "", kParamFormatPAL);
1090 assert(param->getNOptions() == eParamFormatNTSC169);
1091 param->appendOption(kParamFormatNTSC169Label, "", kParamFormatNTSC169);
1092 assert(param->getNOptions() == eParamFormatPAL169);
1093 param->appendOption(kParamFormatPAL169Label, "", kParamFormatPAL169);
1094 assert(param->getNOptions() == eParamFormatHD720);
1095 param->appendOption(kParamFormatHD720Label, "", kParamFormatHD720);
1096 assert(param->getNOptions() == eParamFormatHD);
1097 param->appendOption(kParamFormatHDLabel, "", kParamFormatHD);
1098 assert(param->getNOptions() == eParamFormatUHD4K);
1099 param->appendOption(kParamFormatUHD4KLabel, "", kParamFormatUHD4K);
1100 assert(param->getNOptions() == eParamFormat1kSuper35);
1101 param->appendOption(kParamFormat1kSuper35Label, "", kParamFormat1kSuper35);
1102 assert(param->getNOptions() == eParamFormat1kCinemascope);
1103 param->appendOption(kParamFormat1kCinemascopeLabel, "", kParamFormat1kCinemascope);
1104 assert(param->getNOptions() == eParamFormat2kSuper35);
1105 param->appendOption(kParamFormat2kSuper35Label, "", kParamFormat2kSuper35);
1106 assert(param->getNOptions() == eParamFormat2kCinemascope);
1107 param->appendOption(kParamFormat2kCinemascopeLabel, "", kParamFormat2kCinemascope);
1108 assert(param->getNOptions() == eParamFormat2kDCP);
1109 param->appendOption(kParamFormat2kDCPLabel, "", kParamFormat2kDCP);
1110 assert(param->getNOptions() == eParamFormat4kSuper35);
1111 param->appendOption(kParamFormat4kSuper35Label, "", kParamFormat4kSuper35);
1112 assert(param->getNOptions() == eParamFormat4kCinemascope);
1113 param->appendOption(kParamFormat4kCinemascopeLabel, "", kParamFormat4kCinemascope);
1114 assert(param->getNOptions() == eParamFormat4kDCP);
1115 param->appendOption(kParamFormat4kDCPLabel, "", kParamFormat4kDCP);
1116 assert(param->getNOptions() == eParamFormatSquare256);
1117 param->appendOption(kParamFormatSquare256Label, "", kParamFormatSquare256);
1118 assert(param->getNOptions() == eParamFormatSquare512);
1119 param->appendOption(kParamFormatSquare512Label, "", kParamFormatSquare512);
1120 assert(param->getNOptions() == eParamFormatSquare1k);
1121 param->appendOption(kParamFormatSquare1kLabel, "", kParamFormatSquare1k);
1122 assert(param->getNOptions() == eParamFormatSquare2k);
1123 param->appendOption(kParamFormatSquare2kLabel, "", kParamFormatSquare2k);
1124 param->setDefault(eParamFormatPCVideo);
1125 param->setHint(kParamGeneratorFormatHint);
1126 param->setAnimates(false);
1127 desc.addClipPreferencesSlaveParam(*param);
1128 if (page) {
1129 page->addChild(*param);
1130 }
1131 }
1132
1133 {
1134 int w = 0, h = 0;
1135 double par = -1.;
1136 getFormatResolution(eParamFormatPCVideo, &w, &h, &par);
1137 assert(par != -1);
1138 {
1139 Int2DParamDescriptor* param = desc.defineInt2DParam(kParamGeneratorSize);
1140 param->setLabel(kParamGeneratorSizeLabel);
1141 param->setHint(kParamGeneratorSizeHint);
1142 param->setIsSecretAndDisabled(true);
1143 param->setDefault(w, h);
1144 if (page) {
1145 page->addChild(*param);
1146 }
1147 }
1148
1149 {
1150 DoubleParamDescriptor* param = desc.defineDoubleParam(kParamGeneratorPAR);
1151 param->setLabel(kParamGeneratorPARLabel);
1152 param->setHint(kParamGeneratorPARHint);
1153 param->setIsSecretAndDisabled(true);
1154 param->setRange(0., DBL_MAX);
1155 param->setDisplayRange(0.5, 2.);
1156 param->setDefault(par);
1157 if (page) {
1158 page->addChild(*param);
1159 }
1160 }
1161 }
1162
1163 // btmLeft
1164 {
1165 Double2DParamDescriptor* param = desc.defineDouble2DParam(kParamRectangleInteractBtmLeft);
1166 param->setLabel(kParamRectangleInteractBtmLeftLabel);
1167 param->setDoubleType(eDoubleTypeXYAbsolute);
1168 if ( param->supportsDefaultCoordinateSystem() ) {
1169 param->setDefaultCoordinateSystem(eCoordinatesNormalised); // no need of kParamDefaultsNormalised
1170 } else {
1171 gHostSupportsDefaultCoordinateSystem = false; // no multithread here, see kParamDefaultsNormalised
1172 }
1173 param->setDefault(0., 0.);
1174 param->setRange(-DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX); // Resolve requires range and display range or values are clamped to (-1,1)
1175 param->setDisplayRange(-10000, -10000, 10000, 10000); // Resolve requires display range or values are clamped to (-1,1)
1176 param->setIncrement(1.);
1177 param->setLayoutHint(eLayoutHintNoNewLine, 1);
1178 param->setHint("Coordinates of the bottom left corner of the size rectangle.");
1179 param->setDigits(0);
1180 if (page) {
1181 page->addChild(*param);
1182 }
1183 }
1184
1185 // size
1186 {
1187 Double2DParamDescriptor* param = desc.defineDouble2DParam(kParamRectangleInteractSize);
1188 param->setLabel(kParamRectangleInteractSizeLabel);
1189 param->setDoubleType(eDoubleTypeXY);
1190 if ( param->supportsDefaultCoordinateSystem() ) {
1191 param->setDefaultCoordinateSystem(eCoordinatesNormalised); // no need of kParamDefaultsNormalised
1192 } else {
1193 gHostSupportsDefaultCoordinateSystem = false; // no multithread here, see kParamDefaultsNormalised
1194 }
1195 param->setDefault(1., 1.);
1196 param->setRange(0., 0., DBL_MAX, DBL_MAX); // Resolve requires range and display range or values are clamped to (-1,1)
1197 param->setDisplayRange(0, 0, 10000, 10000); // Resolve requires display range or values are clamped to (-1,1)
1198 param->setIncrement(1.);
1199 param->setDimensionLabels(kParamRectangleInteractSizeDim1, kParamRectangleInteractSizeDim2);
1200 param->setHint("Width and height of the size rectangle.");
1201 param->setIncrement(1.);
1202 param->setDigits(0);
1203 if (page) {
1204 page->addChild(*param);
1205 }
1206 }
1207 }
1208 #endif // OFX_EXTENSIONS_NATRON
1209
1210 if (gHostDescription.supportsMultipleClipPARs) {
1211 //// setPixelAspectRatio
1212 {
1213 BooleanParamDescriptor* param = desc.defineBooleanParam(kParamSetPixelAspectRatio);
1214 param->setLabel(kParamSetPixelAspectRatioLabel);
1215 param->setHint(kParamSetPixelAspectRatioHint);
1216 param->setDefault(false);
1217 param->setAnimates(false);
1218 desc.addClipPreferencesSlaveParam(*param);
1219 if (page) {
1220 page->addChild(*param);
1221 }
1222 }
1223 //// pixelAspectRatio
1224 {
1225 DoubleParamDescriptor* param = desc.defineDoubleParam(kParamOutputPixelAspectRatio);
1226 param->setLabel(kParamOutputPixelAspectRatioLabel);
1227 param->setHint(kParamOutputPixelAspectRatioHint);
1228 param->setDefault(1.);
1229 param->setAnimates(false);
1230 desc.addClipPreferencesSlaveParam(*param);
1231 if (page) {
1232 page->addChild(*param);
1233 }
1234 }
1235 }
1236
1237 if (gHostDescription.supportsSetableFrameRate) {
1238 //// setFrameRate
1239 {
1240 BooleanParamDescriptor* param = desc.defineBooleanParam(kParamSetFrameRate);
1241 param->setLabel(kParamSetFrameRateLabel);
1242 param->setHint(kParamSetFrameRateHint);
1243 param->setDefault(false);
1244 param->setAnimates(false);
1245 desc.addClipPreferencesSlaveParam(*param);
1246 if (page) {
1247 page->addChild(*param);
1248 }
1249 }
1250
1251 //// frameRate
1252 {
1253 DoubleParamDescriptor* param = desc.defineDoubleParam(kParamOutputFrameRate);
1254 param->setLabel(kParamOutputFrameRateLabel);
1255 param->setHint(kParamOutputFrameRateHint);
1256 param->setDefault(24.);
1257 param->setAnimates(false);
1258 desc.addClipPreferencesSlaveParam(*param);
1259 if (page) {
1260 page->addChild(*param);
1261 }
1262 }
1263 }
1264
1265 // clipInfo
1266 {
1267 PushButtonParamDescriptor *param = desc.definePushButtonParam(kParamClipInfo);
1268 param->setLabel(kParamClipInfoLabel);
1269 param->setHint(kParamClipInfoHint);
1270 if (page) {
1271 page->addChild(*param);
1272 }
1273 }
1274 } // NoOpPluginFactory::describeInContext
1275
1276 ImageEffect*
createInstance(OfxImageEffectHandle handle,ContextEnum)1277 NoOpPluginFactory::createInstance(OfxImageEffectHandle handle,
1278 ContextEnum /*context*/)
1279 {
1280 return new NoOpPlugin(handle);
1281 }
1282
1283 static NoOpPluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
1284 mRegisterPluginFactoryInstance(p)
1285
1286 OFXS_NAMESPACE_ANONYMOUS_EXIT
1287