diff --git a/ContactSheet/ContactSheet.cpp b/ContactSheet/ContactSheet.cpp
index 0d17cc4e9..cf59aa227 100644
--- a/ContactSheet/ContactSheet.cpp
+++ b/ContactSheet/ContactSheet.cpp
@@ -294,9 +294,8 @@ ContactSheetPlugin::render(const OFX::RenderArguments &args)
throwSuiteStatusException(kOfxStatFailed);
}
BitDepthEnum dstBitDepth = dst->getPixelDepth();
- PixelComponentEnum dstComponents = dst->getPixelComponents();
+ //PixelComponentEnum dstComponents = dst->getPixelComponents();
const OfxRectI& dstBounds = dst->getBounds();
- const size_t depth = dst->getPixelComponentCount();
assert(dst->getPixelDepth() == eBitDepthFloat);
float* b = (float*)dst->getPixelData();
const size_t bwidth = dstBounds.x2 - dstBounds.x1;
@@ -398,8 +397,8 @@ ContactSheetPlugin::render(const OFX::RenderArguments &args)
throwSuiteStatusException(kOfxStatFailed);
}
BitDepthEnum srcBitDepth = src->getPixelDepth();
- PixelComponentEnum srcComponents = src->getPixelComponents();
- if ( (srcBitDepth != dstBitDepth) || (srcComponents != dstComponents) ) {
+ //PixelComponentEnum srcComponents = src->getPixelComponents();
+ if ( (srcBitDepth != dstBitDepth) /*|| (srcComponents != dstComponents)*/ ) {
throwSuiteStatusException(kOfxStatErrImageFormat);
}
@@ -411,6 +410,7 @@ ContactSheetPlugin::render(const OFX::RenderArguments &args)
const size_t aheight = srcBounds.y2 - srcBounds.y1;
const size_t axstride = src->getPixelComponentCount();
const size_t aystride = awidth * axstride;
+ const size_t depth = std::min(axstride, bxstride);
const OfxRectD from = {0., 0., (double)awidth, (double)aheight};
OfxRectI to;
Coords::toPixelEnclosing(imageRoD, args.renderScale, dstPar, &to);
@@ -596,13 +596,6 @@ ContactSheetPlugin::getClipPreferences(OFX::ClipPreferencesSetter & clipPreferen
{
updateGUI();
- // all inputs and outputs should have the same components
- OFX::PixelComponentEnum outputComps = _dstClip->getPixelComponents();
-
- for (unsigned i = 0; i < _srcClip.size(); ++i) {
- clipPreferences.setClipComponents(*_srcClip[i], outputComps);
- }
-
OfxRectI format = {0, 0, 0, 0};
_resolution->getValue(format.x2, format.y2);
clipPreferences.setOutputFormat(format);
@@ -675,7 +668,7 @@ class ContactSheetInteract : public OverlayInteract {
, _selectionFrame(NULL)
{
_dstClip = effect->fetchClip(kOfxImageEffectOutputClipName);
- assert( _dstClip && (!_dstClip->isConnected() || _dstClip->getPixelComponents() == OFX::ePixelComponentAlpha || _dstClip->getPixelComponents() == OFX::ePixelComponentRGB || _dstClip->getPixelComponents() == OFX::ePixelComponentRGBA) );
+ assert( _dstClip && (!_dstClip->isConnected() || _dstClip->getPixelComponents() == OFX::ePixelComponentRGBA) );
_resolution = effect->fetchInt2DParam(kParamResolution);
_rowsColumns = effect->fetchInt2DParam(kParamRowsColums);
assert(_resolution && _rowsColumns);
@@ -755,7 +748,7 @@ ContactSheetInteract::draw(const OFX::DrawArgs &args)
OfxRGBColourD color = { 0.8, 0.8, 0.8 };
getSuggestedColour(color);
- const OfxPointD& pscale = args.pixelScale;
+ //const OfxPointD& pscale = args.pixelScale;
GLdouble projection[16];
glGetDoublev( GL_PROJECTION_MATRIX, projection);
GLint viewport[4];
@@ -892,9 +885,9 @@ ContactSheetPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
desc.addSupportedBitDepth(eBitDepthFloat);
//desc.addSupportedBitDepth(eBitDepthCustom);
#ifdef OFX_EXTENSIONS_VEGAS
- desc.addSupportedBitDepth(eBitDepthUByteBGRA);
- desc.addSupportedBitDepth(eBitDepthUShortBGRA);
- desc.addSupportedBitDepth(eBitDepthFloatBGRA);
+ //desc.addSupportedBitDepth(eBitDepthUByteBGRA);
+ //desc.addSupportedBitDepth(eBitDepthUShortBGRA);
+ //desc.addSupportedBitDepth(eBitDepthFloatBGRA);
#endif
// set a few flags
@@ -941,7 +934,9 @@ ContactSheetPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc,
srcClip = desc.defineClip("0");
srcClip->setOptional(true);
}
- srcClip->addSupportedComponent(ePixelComponentNone);
+#ifdef OFX_EXTENSIONS_NATRON
+ srcClip->addSupportedComponent(ePixelComponentXY);
+#endif
srcClip->addSupportedComponent(ePixelComponentRGB);
srcClip->addSupportedComponent(ePixelComponentRGBA);
srcClip->addSupportedComponent(ePixelComponentAlpha);
@@ -953,7 +948,9 @@ ContactSheetPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc,
ClipDescriptor *srcClip;
srcClip = desc.defineClip("1");
srcClip->setOptional(true);
- srcClip->addSupportedComponent(ePixelComponentNone);
+#ifdef OFX_EXTENSIONS_NATRON
+ srcClip->addSupportedComponent(ePixelComponentXY);
+#endif
srcClip->addSupportedComponent(ePixelComponentRGB);
srcClip->addSupportedComponent(ePixelComponentRGBA);
srcClip->addSupportedComponent(ePixelComponentAlpha);
@@ -966,7 +963,9 @@ ContactSheetPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc,
for (unsigned i = 2; i < clipSourceCount; ++i) {
ClipDescriptor *srcClip = desc.defineClip( unsignedToString(i) );
srcClip->setOptional(true);
- srcClip->addSupportedComponent(ePixelComponentNone);
+#ifdef OFX_EXTENSIONS_NATRON
+ srcClip->addSupportedComponent(ePixelComponentXY);
+#endif
srcClip->addSupportedComponent(ePixelComponentRGB);
srcClip->addSupportedComponent(ePixelComponentRGBA);
srcClip->addSupportedComponent(ePixelComponentAlpha);
@@ -978,10 +977,7 @@ ContactSheetPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc,
// create the mandated output clip
ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
- dstClip->addSupportedComponent(ePixelComponentNone);
- dstClip->addSupportedComponent(ePixelComponentRGB);
dstClip->addSupportedComponent(ePixelComponentRGBA);
- dstClip->addSupportedComponent(ePixelComponentAlpha);
dstClip->setSupportsTiles(kSupportsTiles);
// make some pages and to things in
diff --git a/LayerContactSheet/Info.plist b/LayerContactSheet/Info.plist
new file mode 100644
index 000000000..ad9d4344c
--- /dev/null
+++ b/LayerContactSheet/Info.plist
@@ -0,0 +1,20 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ LayerContactSheet.ofx
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ BNDL
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 0.0.1d1
+ CSResourcesFileMapped
+
+
+
diff --git a/LayerContactSheet/LayerContactSheet.cpp b/LayerContactSheet/LayerContactSheet.cpp
new file mode 100644
index 000000000..324c68b4c
--- /dev/null
+++ b/LayerContactSheet/LayerContactSheet.cpp
@@ -0,0 +1,850 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * This file is part of openfx-misc ,
+ * Copyright (C) 2013-2016 INRIA
+ *
+ * openfx-misc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * openfx-misc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with openfx-misc. If not, see
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * OFX LayerContactSheet plugin.
+ * LayerContactSheet between inputs.
+ */
+
+#include
+#include
+#include
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+#include
+#endif
+
+#ifdef __APPLE__
+#include
+#else
+#include
+#endif
+
+
+#include "ofxsMacros.h"
+#include "ofxNatron.h"
+#include "ofxsCopier.h"
+#include "ofxsCoords.h"
+#include "ofxsFilter.h"
+#include "ofxsOGLTextRenderer.h"
+
+#ifdef OFX_EXTENSIONS_NUKE
+#include "nuke/fnOfxExtensions.h"
+#endif
+
+using namespace OFX;
+
+
+OFXS_NAMESPACE_ANONYMOUS_ENTER
+
+#define kPluginName "LayerContactSheetOFX"
+#define kPluginGrouping "Merge"
+#define kPluginDescription \
+ "Make a contact sheet from all layers."
+#define kPluginIdentifier "net.sf.openfx.LayerContactSheetOFX"
+#define kPluginVersionMajor 1 // Incrementing this number means that you have broken backwards compatibility of the plug-in.
+#define kPluginVersionMinor 0 // Increment this when you have fixed a bug or made it faster.
+
+#define kSupportsTiles 1
+#define kSupportsMultiResolution 1
+#define kSupportsRenderScale 1
+#define kSupportsMultipleClipPARs false
+#define kSupportsMultipleClipDepths false
+#define kRenderThreadSafety eRenderFullySafe
+
+#define kParamResolution "resolution"
+#define kParamResolutionLabel "Resolution"
+#define kParamResolutionHint \
+ "Resolution of the output image, in pixels."
+
+#define kParamRowsColums "rowsColumns"
+#define kParamRowsColumsLabel "Rows/Columns"
+#define kParamRowsColumsHint \
+ "How many rows and columns in the grid where the input images or frames are arranged."
+
+#define kParamAutoDims "autoDims"
+#define kParamAutoDimsLabel "Automatic Rows/Columns"
+#define kParamAutoDimsHint \
+ "Automatically sets the number of rows/columns to display all layers."
+
+#define kParamGap "gap"
+#define kParamGapLabel "Gap"
+#define kParamGapHint \
+"Gap in pixels around each input or frame."
+
+#define kParamCenter "center"
+#define kParamCenterLabel "Center"
+#define kParamCenterHint \
+"Center each input/frame within its cell."
+
+#define kParamRowOrder "rowOrder"
+#define kParamRowOrderLabel "Row Order"
+#define kParamRowOrderHint \
+"How image rows are populated."
+#define kParamRowOrderOptionTopBottom "TopBottom", "From top to bottom row."
+#define kParamRowOrderOptionBottomTop "BottomTop", "From bottom to top row."
+enum RowOrderEnum {
+ eRowOrderTopBottom = 0,
+ eRowOrderBottomTop,
+};
+
+#define kParamColumnOrder "colOrder"
+#define kParamColumnOrderLabel "Column Order"
+#define kParamColumnOrderHint \
+"How image columns are populated."
+#define kParamColumnOrderOptionLeftRight "LeftRight", "From left to right column."
+#define kParamColumnOrderOptionRightLeft "RightLeft", "From right to left column."
+enum ColumnOrderEnum {
+ eColumnOrderLeftRight = 0,
+ eColumnOrderRightLeft,
+};
+
+#define kParamShowLayerNames "showLayerNames"
+#define kParamShowLayerNamesLabel "Show Layer Names"
+#define kParamShowLayerNamesHint \
+"Display the layer name in the bottom left of each frame."
+
+////////////////////////////////////////////////////////////////////////////////
+/** @brief The plugin that does our work */
+class LayerContactSheetPlugin
+ : public OFX::ImageEffect
+{
+public:
+ /** @brief ctor */
+ LayerContactSheetPlugin(OfxImageEffectHandle handle);
+
+private:
+ /* Override the render */
+ virtual void render(const OFX::RenderArguments &args) OVERRIDE FINAL;
+
+ // override the roi call
+ virtual void getRegionsOfInterest(const OFX::RegionsOfInterestArguments &args, OFX::RegionOfInterestSetter &rois) OVERRIDE FINAL;
+ virtual bool getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod) OVERRIDE FINAL;
+
+ /** Override the get frames needed action */
+ //virtual void getFramesNeeded(const OFX::FramesNeededArguments &args, OFX::FramesNeededSetter &frames) OVERRIDE FINAL;
+
+ /** @brief get the clip preferences */
+ virtual void getClipPreferences(OFX::ClipPreferencesSetter &clipPreferences) OVERRIDE FINAL;
+#ifdef OFX_EXTENSIONS_NUKE
+ virtual void getClipComponents(const ClipComponentsArguments& args, ClipComponentsSetter& clipComponents) OVERRIDE FINAL;
+#endif
+
+ /** @brief called when a clip has just been changed in some way (a rewire maybe) */
+ virtual void changedClip(const InstanceChangedArgs &args, const std::string &clipName) OVERRIDE FINAL;
+ virtual void changedParam(const InstanceChangedArgs &args, const std::string ¶mName) OVERRIDE FINAL;
+
+private:
+
+ void updateGUI();
+
+ // do not need to delete these, the ImageEffect is managing them for us
+ Clip* _dstClip;
+ Clip* _srcClip;
+ Int2DParam *_resolution;
+ Int2DParam* _rowsColumns;
+ BooleanParam* _autoDims;
+ IntParam* _gap;
+ BooleanParam* _center;
+ ChoiceParam* _rowOrder;
+ ChoiceParam* _colOrder;
+ BooleanParam* _showLayerNames;
+};
+
+LayerContactSheetPlugin::LayerContactSheetPlugin(OfxImageEffectHandle handle)
+ : ImageEffect(handle)
+ , _dstClip(NULL)
+ , _srcClip(NULL)
+ , _resolution(NULL)
+ , _rowsColumns(NULL)
+ , _autoDims(NULL)
+ , _gap(NULL)
+ , _center(NULL)
+ , _rowOrder(NULL)
+ , _colOrder(NULL)
+ , _showLayerNames(NULL)
+{
+ _dstClip = fetchClip(kOfxImageEffectOutputClipName);
+ assert( _dstClip && (!_dstClip->isConnected() || _dstClip->getPixelComponents() == OFX::ePixelComponentAlpha || _dstClip->getPixelComponents() == OFX::ePixelComponentRGB || _dstClip->getPixelComponents() == OFX::ePixelComponentRGBA) );
+ _srcClip = fetchClip(kOfxImageEffectSimpleSourceClipName);
+ assert(_srcClip);
+ _resolution = fetchInt2DParam(kParamResolution);
+ _rowsColumns = fetchInt2DParam(kParamRowsColums);
+ assert(_resolution && _rowsColumns);
+ _autoDims = fetchBooleanParam(kParamAutoDims);
+ _gap = fetchIntParam(kParamGap);
+ _center = fetchBooleanParam(kParamCenter);
+ _rowOrder = fetchChoiceParam(kParamRowOrder);
+ _colOrder = fetchChoiceParam(kParamColumnOrder);
+ _showLayerNames = fetchBooleanParam(kParamShowLayerNames);
+
+ updateGUI();
+}
+
+static void
+fitRod(const OfxRectD& srcFormatCanonical,
+ const OfxRectD& cellRoD,
+ int gap,
+ bool center,
+ double* f,
+ OfxRectD* imageRoD)
+{
+ double sw = srcFormatCanonical.x2 - srcFormatCanonical.x1;
+ double sh = srcFormatCanonical.y2 - srcFormatCanonical.y1;
+ OfxRectD cRoD = { cellRoD.x1 + gap / 2, cellRoD.y1 + gap/2, cellRoD.x2 - (gap + 1) / 2, cellRoD.y2 - (gap + 1) / 2};
+ double cw = std::max(1., cRoD.x2 - cRoD.x1);
+ double ch = std::max(1., cRoD.y2 - cRoD.y1);
+ bool fitwidth = sw * ch > sh * cw;
+ *f = fitwidth ? (cw/sw) : (ch / sh);
+ if (center) {
+ imageRoD->x1 = cRoD.x1 + (cw - *f * sw) / 2;
+ imageRoD->x2 = cRoD.x2 - (cw - *f * sw) / 2;
+ imageRoD->y1 = cRoD.y1 + (ch - *f * sh) / 2;
+ imageRoD->y2 = cRoD.y2 - (ch - *f * sh) / 2;
+ } else {
+ imageRoD->x1 = cRoD.x1;
+ imageRoD->x2 = cRoD.x1 + *f * sw;
+ imageRoD->y1 = cRoD.y1;
+ imageRoD->y2 = cRoD.y1 + *f * sh;
+ }
+}
+
+void
+LayerContactSheetPlugin::render(const OFX::RenderArguments &args)
+{
+ const double time = args.time;
+
+ // do the rendering
+ std::auto_ptr dst( _dstClip->fetchImage(time) );
+ if ( !dst.get() ) {
+ throwSuiteStatusException(kOfxStatFailed);
+ }
+ if ( (dst->getRenderScale().x != args.renderScale.x) ||
+ ( dst->getRenderScale().y != args.renderScale.y) ||
+ ( ( dst->getField() != eFieldNone) /* for DaVinci Resolve */ && ( dst->getField() != args.fieldToRender) ) ) {
+ setPersistentMessage(Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
+ throwSuiteStatusException(kOfxStatFailed);
+ }
+ BitDepthEnum dstBitDepth = dst->getPixelDepth();
+ //PixelComponentEnum dstComponents = dst->getPixelComponents();
+ const OfxRectI& dstBounds = dst->getBounds();
+ assert(dst->getPixelDepth() == eBitDepthFloat);
+ float* b = (float*)dst->getPixelData();
+ const size_t bwidth = dstBounds.x2 - dstBounds.x1;
+ const size_t bheight = dstBounds.y2 - dstBounds.y1;
+ const size_t bxstride = dst->getPixelComponentCount();
+ const size_t bystride = bwidth * bxstride;
+ // clear the renderWindow
+ fillBlack( *this, args.renderWindow, dst.get() );
+
+ OfxRectD rod;
+ {
+ int w, h;
+ _resolution->getValue(w, h);
+ double par = _dstClip->getPixelAspectRatio();
+ OfxPointD rs1 = {1., 1.};
+ OfxRectI rodpixel = {0, 0, w, h};
+ Coords::toCanonical(rodpixel, rs1, par, &rod);
+ }
+ bool topbottom = (_rowOrder->getValueAtTime(time) == eRowOrderTopBottom);
+ bool leftright = (_colOrder->getValueAtTime(time) == eColumnOrderLeftRight);
+ int gap = _gap->getValueAtTime(time);
+ bool center = _center->getValueAtTime(time);
+ double dstPar = _dstClip->getPixelAspectRatio();
+ OfxRectD renderWindowCanonical;
+ Coords::toCanonical(args.renderWindow, args.renderScale, dstPar, &renderWindowCanonical);
+
+ assert( kSupportsMultipleClipPARs || !_srcClip || _srcClip->getPixelAspectRatio() == _dstClip->getPixelAspectRatio() );
+ assert( kSupportsMultipleClipDepths || !_srcClip || _srcClip->getPixelDepth() == _dstClip->getPixelDepth() );
+
+ OfxRectD srcFormatCanonical;
+ {
+ OfxRectI srcFormat;
+ _srcClip->getFormat(srcFormat);
+ double srcPar = _srcClip->getPixelAspectRatio();
+ if ( OFX::Coords::rectIsEmpty(srcFormat) ) {
+ // no format is available, use the RoD instead
+ srcFormatCanonical = _srcClip->getRegionOfDefinition(time);
+ } else {
+ const OfxPointD rs1 = {1., 1.};
+ Coords::toCanonical(srcFormat, rs1, srcPar, &srcFormatCanonical);
+ }
+ }
+
+ std::vector components;
+ _srcClip->getComponentsPresent(&components);
+
+ // now, for each clip, compute the required region of interest, which is the union of the intersection of each cell with the renderWindow
+ int rows, columns;
+ if ( !_autoDims->getValueAtTime(time) ) {
+ _rowsColumns->getValueAtTime(time, rows, columns);
+ } else {
+ std::size_t n = components.size();
+ double w = rod.x2 - rod.x1;
+ double h = rod.y2 - rod.y1;
+ double sw = srcFormatCanonical.x2 - srcFormatCanonical.x1;
+ double sh = srcFormatCanonical.y2 - srcFormatCanonical.y1;
+ columns = std::ceil( std::sqrt( (n * w * sh) / (h * sw) ) );
+ rows = std::ceil( n / (double) columns);
+ }
+
+ for (std::size_t layer = 0; layer < components.size(); ++layer) {
+ int r = layer / columns;
+ int c = layer % columns;
+ if (r >= rows) {
+ continue;
+ }
+ if (topbottom) {
+ r = rows - 1 - r;
+ }
+ if (!leftright) {
+ c = columns - 1 - c;
+ }
+ // now compute the four corners of the cell in the rod
+ OfxRectD cellRoD = {
+ rod.x1 + c * (rod.x2 - rod.x1) / columns,
+ rod.y1 + r * (rod.y2 - rod.y1) / rows,
+ rod.x1 + (c + 1) * (rod.x2 - rod.x1) / columns,
+ rod.y1 + (r + 1) * (rod.y2 - rod.y1) / rows
+ };
+
+ // and the four corners of the image area in the dest rod
+ double f = 1;
+ OfxRectD imageRoD = {0., 0., 0., 0.};
+ fitRod(srcFormatCanonical, cellRoD, gap, center, &f, &imageRoD);
+
+ //- intersect with the render window
+ OfxRectD imageRoDClipped;
+ if (Coords::rectIntersection(renderWindowCanonical, imageRoD, &imageRoDClipped)) {
+
+ //render:
+ //- get the the src Image
+ std::auto_ptr src( ( _srcClip && _srcClip->isConnected() ) ?
+ _srcClip->fetchImagePlane(time, components[layer].c_str()) : 0 );
+ if ( src.get() ) {
+ if ( (src->getRenderScale().x != args.renderScale.x) ||
+ ( src->getRenderScale().y != args.renderScale.y) ||
+ ( ( src->getField() != eFieldNone) /* for DaVinci Resolve */ && ( src->getField() != args.fieldToRender) ) ) {
+ setPersistentMessage(Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
+ throwSuiteStatusException(kOfxStatFailed);
+ }
+ BitDepthEnum srcBitDepth = src->getPixelDepth();
+ //PixelComponentEnum srcComponents = src->getPixelComponents();
+ if ( (srcBitDepth != dstBitDepth) /*|| (srcComponents != dstComponents)*/ ) {
+ throwSuiteStatusException(kOfxStatErrImageFormat);
+ }
+
+ //- draw it at the right place
+ const OfxRectI& srcBounds = src->getBounds();
+ assert(src->getPixelDepth() == eBitDepthFloat);
+ const float* a = (const float*)src->getPixelData();
+ const size_t awidth = srcBounds.x2 - srcBounds.x1;
+ const size_t aheight = srcBounds.y2 - srcBounds.y1;
+ const size_t axstride = src->getPixelComponentCount();
+ const size_t aystride = awidth * axstride;
+ const size_t depth = std::min(axstride, bxstride);
+ const OfxRectD from = {0., 0., (double)awidth, (double)aheight};
+ OfxRectI to;
+ Coords::toPixelEnclosing(imageRoD, args.renderScale, dstPar, &to);
+ to.x1 -= dstBounds.x1;
+ to.y1 -= dstBounds.y1;
+ to.x2 -= dstBounds.x1;
+ to.y2 -= dstBounds.y1;
+
+ ofxsFilterResize2d(a, awidth, aheight, axstride, aystride, depth,
+ from, /*zeroOutside=*/false,
+ b, bwidth, bheight, bxstride, bystride,
+ to);
+ }
+ }
+ }
+}
+
+
+// override the roi call
+// Required if the plugin requires a region from the inputs which is different from the rendered region of the output.
+// (this is the case here)
+void
+LayerContactSheetPlugin::getRegionsOfInterest(const OFX::RegionsOfInterestArguments &args,
+ OFX::RegionOfInterestSetter &rois)
+{
+ const double time = args.time;
+
+ // ask for the full format
+ OfxRectD srcFormatCanonical;
+ {
+ OfxRectI srcFormat;
+ _srcClip->getFormat(srcFormat);
+ double srcPar = _srcClip->getPixelAspectRatio();
+ if ( OFX::Coords::rectIsEmpty(srcFormat) ) {
+ // no format is available, use the RoD instead
+ srcFormatCanonical = _srcClip->getRegionOfDefinition(time);
+ } else {
+ const OfxPointD rs1 = {1., 1.};
+ Coords::toCanonical(srcFormat, rs1, srcPar, &srcFormatCanonical);
+ }
+ }
+ rois.setRegionOfInterest(*_srcClip, srcFormatCanonical);
+}
+
+bool
+LayerContactSheetPlugin::getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args,
+ OfxRectD &rod)
+{
+ const double time = args.time;
+ int w, h;
+ _resolution->getValueAtTime(time, w, h);
+ double par = _dstClip->getPixelAspectRatio();
+ OfxPointD rs1 = {1., 1.};
+ OfxRectI rodpixel = {0, 0, w, h};
+ Coords::toCanonical(rodpixel, rs1, par, &rod);
+
+ return true;
+}
+
+
+
+/* Override the clip preferences */
+void
+LayerContactSheetPlugin::getClipPreferences(OFX::ClipPreferencesSetter & clipPreferences)
+{
+ updateGUI();
+
+ OfxRectI format = {0, 0, 0, 0};
+ _resolution->getValue(format.x2, format.y2);
+ clipPreferences.setOutputFormat(format);
+ //clipPreferences.setPixelAspectRatio(*_dstClip, par);
+}
+
+#ifdef OFX_EXTENSIONS_NUKE
+void
+LayerContactSheetPlugin::getClipComponents(const ClipComponentsArguments& args,
+ ClipComponentsSetter& clipComponents)
+{
+ // no pass-through
+ clipComponents.setPassThroughClip(NULL, args.time, args.view);
+
+ // produces RGBA only
+ clipComponents.addClipComponents(*_dstClip, ePixelComponentRGBA);
+
+ // ask for the first rows * cols first components from the input
+ std::vector components;
+ _srcClip->getComponentsPresent(&components);
+
+}
+#endif
+
+void
+LayerContactSheetPlugin::changedClip(const InstanceChangedArgs & /*args*/,
+ const std::string & /*clipName*/)
+{
+}
+
+void
+LayerContactSheetPlugin::changedParam(const InstanceChangedArgs &/*args*/,
+ const std::string ¶mName)
+{
+ if (paramName == kParamAutoDims) {
+ updateGUI();
+ }
+}
+
+void
+LayerContactSheetPlugin::updateGUI()
+{
+ bool autoDims = _autoDims->getValue();
+ _rowsColumns->setEnabled(!autoDims);
+}
+
+//////////// INTERACT
+
+class LayerContactSheetInteract : public OverlayInteract {
+
+public:
+ LayerContactSheetInteract(OfxInteractHandle handle, ImageEffect* effect)
+ : OverlayInteract(handle)
+ , _srcClip(NULL)
+ , _dstClip(NULL)
+ , _resolution(NULL)
+ , _rowsColumns(NULL)
+ , _autoDims(NULL)
+ , _gap(NULL)
+ , _center(NULL)
+ , _rowOrder(NULL)
+ , _colOrder(NULL)
+ , _showLayerNames(NULL)
+ {
+ _srcClip = effect->fetchClip(kOfxImageEffectSimpleSourceClipName);
+ _dstClip = effect->fetchClip(kOfxImageEffectOutputClipName);
+ assert( _dstClip && (!_dstClip->isConnected() || _dstClip->getPixelComponents() == OFX::ePixelComponentAlpha || _dstClip->getPixelComponents() == OFX::ePixelComponentRGB || _dstClip->getPixelComponents() == OFX::ePixelComponentRGBA) );
+ _resolution = effect->fetchInt2DParam(kParamResolution);
+ _rowsColumns = effect->fetchInt2DParam(kParamRowsColums);
+ _autoDims = effect->fetchBooleanParam(kParamAutoDims);
+ _gap = effect->fetchIntParam(kParamGap);
+ _center = effect->fetchBooleanParam(kParamCenter);
+ _rowOrder = effect->fetchChoiceParam(kParamRowOrder);
+ _colOrder = effect->fetchChoiceParam(kParamColumnOrder);
+ _showLayerNames = effect->fetchBooleanParam(kParamShowLayerNames);
+ }
+
+private:
+ // overridden functions from OFX::Interact to do things
+ virtual bool draw(const OFX::DrawArgs &args) OVERRIDE FINAL;
+
+private:
+ Clip* _srcClip;
+ Clip* _dstClip;
+ Int2DParam *_resolution;
+ Int2DParam* _rowsColumns;
+ BooleanParam* _autoDims;
+ IntParam* _gap;
+ BooleanParam* _center;
+ ChoiceParam* _rowOrder;
+ ChoiceParam* _colOrder;
+ BooleanParam* _showLayerNames;
+
+};
+
+// draw the interact
+bool
+LayerContactSheetInteract::draw(const OFX::DrawArgs &args)
+{
+ const double time = args.time;
+
+ if ( !_showLayerNames->getValueAtTime(time) ) {
+ return false;
+ }
+
+ OfxRectD rod;
+ {
+ int w, h;
+ _resolution->getValue(w, h);
+ double par = _dstClip->getPixelAspectRatio();
+ OfxPointD rs1 = {1., 1.};
+ OfxRectI rodpixel = {0, 0, w, h};
+ Coords::toCanonical(rodpixel, rs1, par, &rod);
+ }
+ bool topbottom = (_rowOrder->getValueAtTime(time) == eRowOrderTopBottom);
+ bool leftright = (_colOrder->getValueAtTime(time) == eColumnOrderLeftRight);
+ int gap = _gap->getValueAtTime(time);
+ bool center = _center->getValueAtTime(time);
+ //double dstPar = _dstClip->getPixelAspectRatio();
+
+ OfxRectD srcFormatCanonical;
+ {
+ OfxRectI srcFormat;
+ _srcClip->getFormat(srcFormat);
+ double srcPar = _srcClip->getPixelAspectRatio();
+ if ( OFX::Coords::rectIsEmpty(srcFormat) ) {
+ // no format is available, use the RoD instead
+ srcFormatCanonical = _srcClip->getRegionOfDefinition(time);
+ } else {
+ const OfxPointD rs1 = {1., 1.};
+ Coords::toCanonical(srcFormat, rs1, srcPar, &srcFormatCanonical);
+ }
+ }
+
+ std::vector components;
+ _srcClip->getComponentsPresent(&components);
+
+ // now, for each clip, compute the required region of interest, which is the union of the intersection of each cell with the renderWindow
+ int rows, columns;
+ if ( !_autoDims->getValueAtTime(time) ) {
+ _rowsColumns->getValueAtTime(time, rows, columns);
+ } else {
+ std::size_t n = components.size();
+ double w = rod.x2 - rod.x1;
+ double h = rod.y2 - rod.y1;
+ double sw = srcFormatCanonical.x2 - srcFormatCanonical.x1;
+ double sh = srcFormatCanonical.y2 - srcFormatCanonical.y1;
+ columns = std::ceil( std::sqrt( (n * w * sh) / (h * sw) ) );
+ rows = std::ceil( n / (double) columns);
+ }
+
+ OfxRGBColourD color = { 0.8, 0.8, 0.8 };
+ getSuggestedColour(color);
+ //const OfxPointD& pscale = args.pixelScale;
+ GLdouble projection[16];
+ glGetDoublev( GL_PROJECTION_MATRIX, projection);
+ GLint viewport[4];
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ OfxPointD shadow; // how much to translate GL_PROJECTION to get exactly one pixel on screen
+ shadow.x = 2. / (projection[0] * viewport[2]);
+ shadow.y = 2. / (projection[5] * viewport[3]);
+
+ for (std::size_t layer = 0; layer < components.size(); ++layer) {
+ std::string name = components[layer];
+ {
+ std::size_t first_underline = name.find_first_of('_');
+ std::size_t second_underline = std::string::npos;
+ if (first_underline != std::string::npos) {
+ second_underline = name.find_first_of('_', first_underline + 1);
+ name = name.substr(first_underline + 1, second_underline - (first_underline + 1));
+ }
+ }
+ int r = layer / columns;
+ int c = layer % columns;
+ if (r >= rows) {
+ continue;
+ }
+ if (topbottom) {
+ r = rows - 1 - r;
+ }
+ if (!leftright) {
+ c = columns - 1 - c;
+ }
+ // now compute the four corners of the cell in the rod
+ OfxRectD cellRoD = {
+ rod.x1 + c * (rod.x2 - rod.x1) / columns,
+ rod.y1 + r * (rod.y2 - rod.y1) / rows,
+ rod.x1 + (c + 1) * (rod.x2 - rod.x1) / columns,
+ rod.y1 + (r + 1) * (rod.y2 - rod.y1) / rows
+ };
+
+ // and the four corners of the image area in the dest rod
+ double f = 1;
+ OfxRectD imageRoD = {0., 0., 0., 0.};
+ fitRod(srcFormatCanonical, cellRoD, gap, center, &f, &imageRoD);
+
+ // Draw everything twice
+ // l = 0: shadow
+ // l = 1: drawing
+ for (int l = 0; l < 2; ++l) {
+ // shadow (uses GL_PROJECTION)
+ glMatrixMode(GL_PROJECTION);
+ int direction = (l == 0) ? 1 : -1;
+ // translate (1,-1) pixels
+ glTranslated(direction * shadow.x, -direction * shadow.y, 0);
+ glMatrixMode(GL_MODELVIEW); // Modelview should be used on Nuke
+
+ glColor3f(color.r * l, color.g * l, color.b * l);
+
+ TextRenderer::bitmapString( imageRoD.x1, imageRoD.y1, name.c_str() );
+ }
+ }
+
+ return true;
+}
+
+
+
+//////////// FACTORY
+
+mDeclarePluginFactory(LayerContactSheetPluginFactory, {}, {});
+
+class LayerContactSheetOverlayDescriptor : public DefaultEffectOverlayDescriptor {};
+
+void
+LayerContactSheetPluginFactory::describe(OFX::ImageEffectDescriptor &desc)
+{
+ // basic labels
+ desc.setLabel(kPluginName);
+ desc.setPluginGrouping(kPluginGrouping);
+ desc.setPluginDescription(kPluginDescription);
+
+ // add the supported contexts
+ desc.addSupportedContext(eContextGeneral);
+ desc.addSupportedContext(eContextFilter);
+
+ // add supported pixel depths
+ //desc.addSupportedBitDepth(eBitDepthNone);
+ //desc.addSupportedBitDepth(eBitDepthUByte);
+ //desc.addSupportedBitDepth(eBitDepthUShort);
+ //desc.addSupportedBitDepth(eBitDepthHalf);
+ desc.addSupportedBitDepth(eBitDepthFloat);
+ //desc.addSupportedBitDepth(eBitDepthCustom);
+#ifdef OFX_EXTENSIONS_VEGAS
+ //desc.addSupportedBitDepth(eBitDepthUByteBGRA);
+ //desc.addSupportedBitDepth(eBitDepthUShortBGRA);
+ //desc.addSupportedBitDepth(eBitDepthFloatBGRA);
+#endif
+
+ // set a few flags
+ desc.setSingleInstance(false);
+ desc.setHostFrameThreading(false);
+ desc.setSupportsMultiResolution(kSupportsMultiResolution);
+ desc.setSupportsTiles(kSupportsTiles);
+ desc.setTemporalClipAccess(true);
+ desc.setRenderTwiceAlways(false);
+ desc.setSupportsMultipleClipPARs(kSupportsMultipleClipPARs);
+ desc.setSupportsMultipleClipDepths(kSupportsMultipleClipDepths);
+#ifdef OFX_EXTENSIONS_NUKE
+ // Enable transform by the host.
+ // It is only possible for transforms which can be represented as a 3x3 matrix.
+ desc.setCanTransform(false);
+
+ desc.setIsMultiPlanar(true);
+ desc.setPassThroughForNotProcessedPlanes(ePassThroughLevelBlockAllNonRenderedPlanes);
+#endif
+ desc.setRenderThreadSafety(kRenderThreadSafety);
+#ifdef OFX_EXTENSIONS_NATRON
+ desc.setChannelSelector(ePixelComponentNone);
+#endif
+
+ desc.setOverlayInteractDescriptor( new LayerContactSheetOverlayDescriptor);
+}
+
+void
+LayerContactSheetPluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc,
+ OFX::ContextEnum /*context*/)
+{
+ // Source clip only in the filter context
+ // create the mandated source clip
+ {
+ ClipDescriptor *srcClip;
+ srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
+ srcClip->addSupportedComponent(ePixelComponentNone);
+ srcClip->addSupportedComponent(ePixelComponentXY);
+ srcClip->addSupportedComponent(ePixelComponentRGB);
+ srcClip->addSupportedComponent(ePixelComponentRGBA);
+ srcClip->addSupportedComponent(ePixelComponentAlpha);
+ srcClip->setTemporalClipAccess(false);
+ srcClip->setSupportsTiles(kSupportsTiles);
+ srcClip->setIsMask(false);
+ }
+
+ // create the mandated output clip
+ ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
+ dstClip->addSupportedComponent(ePixelComponentRGBA);
+ dstClip->setSupportsTiles(kSupportsTiles);
+
+ // make some pages and to things in
+ PageParamDescriptor *page = desc.definePageParam("Controls");
+
+ // resolution
+ {
+ Int2DParamDescriptor *param = desc.defineInt2DParam(kParamResolution);
+ param->setLabel(kParamResolutionLabel);
+ param->setHint(kParamResolutionHint);
+ param->setDefault(3072, 2048);
+ param->setRange(1, 1, INT_MAX, INT_MAX);
+ param->setDisplayRange(256, 256, 4096, 4096);
+ param->setAnimates(false);
+ if (page) {
+ page->addChild(*param);
+ }
+ }
+
+ // rowsColumns
+ {
+ Int2DParamDescriptor *param = desc.defineInt2DParam(kParamRowsColums);
+ param->setLabel(kParamRowsColumsLabel);
+ param->setHint(kParamRowsColumsHint);
+ param->setDefault(3, 4);
+ param->setRange(1, 1, INT_MAX, INT_MAX);
+ param->setDisplayRange(1, 1, 32, 32);
+ param->setAnimates(false);
+ param->setLayoutHint(eLayoutHintNoNewLine, 1);
+ if (page) {
+ page->addChild(*param);
+ }
+ }
+
+ // autoDims
+ {
+ BooleanParamDescriptor *param = desc.defineBooleanParam(kParamAutoDims);
+ param->setLabel(kParamAutoDimsLabel);
+ param->setHint(kParamAutoDimsHint);
+ param->setAnimates(false);
+ param->setDefault(true);
+ if (page) {
+ page->addChild(*param);
+ }
+ }
+
+ // gap
+ {
+ IntParamDescriptor *param = desc.defineIntParam(kParamGap);
+ param->setLabel(kParamGapLabel);
+ param->setHint(kParamGapHint);
+ param->setDefault(0);
+ param->setRange(0, INT_MAX);
+ param->setDisplayRange(0, 100);
+ param->setAnimates(false);
+ param->setLayoutHint(eLayoutHintNoNewLine, 1);
+ if (page) {
+ page->addChild(*param);
+ }
+ }
+
+ // center
+ {
+ BooleanParamDescriptor *param = desc.defineBooleanParam(kParamCenter);
+ param->setLabel(kParamCenterLabel);
+ param->setHint(kParamCenterHint);
+ param->setAnimates(false);
+ if (page) {
+ page->addChild(*param);
+ }
+ }
+
+ // rowOrder
+ {
+ ChoiceParamDescriptor *param = desc.defineChoiceParam(kParamRowOrder);
+ param->setLabel(kParamRowOrderLabel);
+ param->setHint(kParamRowOrderHint);
+ param->setAnimates(false);
+ assert(param->getNOptions() == (int)eRowOrderTopBottom);
+ param->appendOption(kParamRowOrderOptionTopBottom);
+ assert(param->getNOptions() == (int)eRowOrderBottomTop);
+ param->appendOption(kParamRowOrderOptionBottomTop);
+ if (page) {
+ page->addChild(*param);
+ }
+ }
+
+ // colOrder
+ {
+ ChoiceParamDescriptor *param = desc.defineChoiceParam(kParamColumnOrder);
+ param->setLabel(kParamColumnOrderLabel);
+ param->setHint(kParamColumnOrderHint);
+ param->setAnimates(false);
+ assert(param->getNOptions() == (int)eColumnOrderLeftRight);
+ param->appendOption(kParamColumnOrderOptionLeftRight);
+ assert(param->getNOptions() == (int)eColumnOrderRightLeft);
+ param->appendOption(kParamColumnOrderOptionRightLeft);
+ if (page) {
+ page->addChild(*param);
+ }
+ }
+
+ // showLayerNames
+ {
+ BooleanParamDescriptor *param = desc.defineBooleanParam(kParamShowLayerNames);
+ param->setLabel(kParamShowLayerNamesLabel);
+ param->setHint(kParamShowLayerNamesHint);
+ param->setAnimates(false);
+ param->setEvaluateOnChange(false);
+ if (page) {
+ page->addChild(*param);
+ }
+ }
+
+} // LayerContactSheetPluginFactory::describeInContext
+
+OFX::ImageEffect*
+LayerContactSheetPluginFactory::createInstance(OfxImageEffectHandle handle,
+ OFX::ContextEnum /*context*/)
+{
+ return new LayerContactSheetPlugin(handle);
+}
+
+static LayerContactSheetPluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
+mRegisterPluginFactoryInstance(p)
+
+OFXS_NAMESPACE_ANONYMOUS_EXIT
diff --git a/LayerContactSheet/Makefile b/LayerContactSheet/Makefile
new file mode 100644
index 000000000..f2c59448c
--- /dev/null
+++ b/LayerContactSheet/Makefile
@@ -0,0 +1,7 @@
+PLUGINOBJECTS = LayerContactSheet.o
+PLUGINNAME = LayerContactSheet
+#RESOURCES = net.sf.openfx.switchPlugin.png net.sf.openfx.switchPlugin.svg
+
+TOP_SRCDIR = ..
+include $(TOP_SRCDIR)/Makefile.master
+
diff --git a/Makefile b/Makefile
index abda1d7f5..2724251e0 100644
--- a/Makefile
+++ b/Makefile
@@ -42,6 +42,7 @@ Invert \
JoinViews \
Keyer \
KeyMix \
+LayerContactSheet \
Log2Lin \
MatteMonitor \
Merge \
diff --git a/Misc.files b/Misc.files
index a7100c267..3fb531430 100644
--- a/Misc.files
+++ b/Misc.files
@@ -54,6 +54,7 @@ ImageStatistics/ImageStatistics.cpp
Invert/Invert.cpp
JoinViews/JoinViews.cpp
Keyer/Keyer.cpp
+LayerContactSheet/LayerContactSheet.cpp
MatteMonitor/MatteMonitor.cpp
Merge/Merge.cpp
Mirror/Mirror.cpp
diff --git a/Misc.xcodeproj/project.pbxproj b/Misc.xcodeproj/project.pbxproj
index 7741c1658..af5adab39 100644
--- a/Misc.xcodeproj/project.pbxproj
+++ b/Misc.xcodeproj/project.pbxproj
@@ -830,6 +830,25 @@
1EB00C771EDEF90E006CA180 /* ContactSheet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EB00C741EDEF75D006CA180 /* ContactSheet.cpp */; };
1EB00C781EDEF91D006CA180 /* ContactSheet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EB00C741EDEF75D006CA180 /* ContactSheet.cpp */; };
1EB00C791EE0418D006CA180 /* ContactSheet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EB00C741EDEF75D006CA180 /* ContactSheet.cpp */; };
+ 1EB00C7D1EE078D2006CA180 /* ofxsCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E3E3CB517995D5C005F2132 /* ofxsCore.cpp */; };
+ 1EB00C7E1EE078D2006CA180 /* tinythread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EF77B701E4A3878005C4845 /* tinythread.cpp */; };
+ 1EB00C7F1EE078D2006CA180 /* ofxsImageEffect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E3E3CB617995D5C005F2132 /* ofxsImageEffect.cpp */; };
+ 1EB00C801EE078D2006CA180 /* ofxsInteract.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E3E3CB717995D5C005F2132 /* ofxsInteract.cpp */; };
+ 1EB00C811EE078D2006CA180 /* ofxsGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E75A0311A87BA37005BAA36 /* ofxsGenerator.cpp */; };
+ 1EB00C821EE078D2006CA180 /* ofxsLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E3E3CB817995D5C005F2132 /* ofxsLog.cpp */; };
+ 1EB00C831EE078D2006CA180 /* ofxsThreadSuite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EF77B721E4A3998005C4845 /* ofxsThreadSuite.cpp */; };
+ 1EB00C841EE078D2006CA180 /* ofxsMultiThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E3E3CB917995D5C005F2132 /* ofxsMultiThread.cpp */; };
+ 1EB00C851EE078D2006CA180 /* ofxsParams.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E3E3CBA17995D5C005F2132 /* ofxsParams.cpp */; };
+ 1EB00C861EE078D2006CA180 /* ofxsProperty.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E3E3CBB17995D5C005F2132 /* ofxsProperty.cpp */; };
+ 1EB00C871EE078D2006CA180 /* ofxsPropertyValidation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E3E3CBC17995D5C005F2132 /* ofxsPropertyValidation.cpp */; };
+ 1EB00C881EE078D2006CA180 /* ofxsRectangleInteract.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E9B5F53198A51840095C8AA /* ofxsRectangleInteract.cpp */; };
+ 1EB00C8A1EE078D2006CA180 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E551F5A179950EC00A4135C /* OpenGL.framework */; };
+ 1EB00C8C1EE078D2006CA180 /* net.sf.openfx.CheckerBoardPlugin.png in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1E75A0801A88E260005BAA36 /* net.sf.openfx.CheckerBoardPlugin.png */; };
+ 1EB00C8D1EE078D2006CA180 /* net.sf.openfx.CheckerBoardPlugin.svg in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1E75A0811A88E260005BAA36 /* net.sf.openfx.CheckerBoardPlugin.svg */; };
+ 1EB00C931EE0792A006CA180 /* ofxsOGLFontData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E9B5F4D198A51840095C8AA /* ofxsOGLFontData.cpp */; };
+ 1EB00C951EE0792A006CA180 /* ofxsOGLTextRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E9B5F4F198A51840095C8AA /* ofxsOGLTextRenderer.cpp */; };
+ 1EB00C9B1EE07A53006CA180 /* LayerContactSheet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EB00C991EE07A4A006CA180 /* LayerContactSheet.cpp */; };
+ 1EB00C9C1EE07A55006CA180 /* LayerContactSheet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EB00C991EE07A4A006CA180 /* LayerContactSheet.cpp */; };
1EB0A4401AA1EDB100F9C93E /* TestPosition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EB0A43E1AA1EDB100F9C93E /* TestPosition.cpp */; };
1EB0A4431AA1F03C00F9C93E /* TestGroups.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EB0A4411AA1F03C00F9C93E /* TestGroups.cpp */; };
1EB0A4441AA2002700F9C93E /* ofxsTransform3x3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1E9B5F57198A51840095C8AA /* ofxsTransform3x3.cpp */; };
@@ -2579,6 +2598,17 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 1EB00C8B1EE078D2006CA180 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 7;
+ files = (
+ 1EB00C8C1EE078D2006CA180 /* net.sf.openfx.CheckerBoardPlugin.png in CopyFiles */,
+ 1EB00C8D1EE078D2006CA180 /* net.sf.openfx.CheckerBoardPlugin.svg in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
1EB0A4701AA202EC00F9C93E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -3672,6 +3702,10 @@
1EB00C741EDEF75D006CA180 /* ContactSheet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContactSheet.cpp; sourceTree = ""; };
1EB00C751EDEF75D006CA180 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
1EB00C761EDEF75D006CA180 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; };
+ 1EB00C911EE078D2006CA180 /* LayerContactSheet.ofx.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LayerContactSheet.ofx.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1EB00C981EE07A4A006CA180 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 1EB00C991EE07A4A006CA180 /* LayerContactSheet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LayerContactSheet.cpp; sourceTree = ""; };
+ 1EB00C9A1EE07A4A006CA180 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; };
1EB0A43E1AA1EDB100F9C93E /* TestPosition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestPosition.cpp; sourceTree = ""; };
1EB0A4411AA1F03C00F9C93E /* TestGroups.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestGroups.cpp; sourceTree = ""; };
1EB0A45B1AA202DF00F9C93E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
@@ -4334,6 +4368,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 1EB00C891EE078D2006CA180 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1EB00C8A1EE078D2006CA180 /* OpenGL.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
1EB0A46E1AA202EC00F9C93E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -5087,6 +5129,7 @@
1E2212091E535F170069EB8D /* Card3D.ofx.bundle */,
1EE3F3BD1EC9C3CB00B61988 /* Threshold.ofx.bundle */,
1EB00C711EDEF686006CA180 /* ContactSheet.ofx.bundle */,
+ 1EB00C911EE078D2006CA180 /* LayerContactSheet.ofx.bundle */,
);
name = Products;
sourceTree = "";
@@ -5150,6 +5193,7 @@
1EDE1BAF182D39DA002392CB /* JoinViews */,
1ECF2FA019F51D6700E91A38 /* Keyer */,
1EBEC6021D928EBB00127BC7 /* KeyMix */,
+ 1EB00C971EE07A17006CA180 /* LayerContactSheet */,
1E89B5721D81A77E00F61E6B /* Log2Lin */,
1E2D33D51C3FB21A004E2F03 /* MatteMonitor */,
D74121CA18F9C99300A81F8B /* Merge */,
@@ -5625,6 +5669,16 @@
path = ContactSheet;
sourceTree = "";
};
+ 1EB00C971EE07A17006CA180 /* LayerContactSheet */ = {
+ isa = PBXGroup;
+ children = (
+ 1EB00C981EE07A4A006CA180 /* Info.plist */,
+ 1EB00C991EE07A4A006CA180 /* LayerContactSheet.cpp */,
+ 1EB00C9A1EE07A4A006CA180 /* Makefile */,
+ );
+ path = LayerContactSheet;
+ sourceTree = "";
+ };
1EB0A45A1AA202AE00F9C93E /* Position */ = {
isa = PBXGroup;
children = (
@@ -6845,6 +6899,23 @@
productReference = 1EB00C711EDEF686006CA180 /* ContactSheet.ofx.bundle */;
productType = "com.apple.product-type.bundle";
};
+ 1EB00C7A1EE078D2006CA180 /* LayerContactSheet.ofx */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1EB00C8E1EE078D2006CA180 /* Build configuration list for PBXNativeTarget "LayerContactSheet.ofx" */;
+ buildPhases = (
+ 1EB00C7B1EE078D2006CA180 /* Sources */,
+ 1EB00C891EE078D2006CA180 /* Frameworks */,
+ 1EB00C8B1EE078D2006CA180 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = LayerContactSheet.ofx;
+ productName = basic.ofx;
+ productReference = 1EB00C911EE078D2006CA180 /* LayerContactSheet.ofx.bundle */;
+ productType = "com.apple.product-type.bundle";
+ };
1EB0A4601AA202EC00F9C93E /* Position.ofx */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1EB0A4751AA202EC00F9C93E /* Build configuration list for PBXNativeTarget "Position.ofx" */;
@@ -7604,6 +7675,7 @@
1EDE1B9D182D3985002392CB /* JoinViews.ofx */,
1ECF2F8A19F51D3400E91A38 /* Keyer.ofx */,
1EBEC5ED1D928E9E00127BC7 /* KeyMix.ofx */,
+ 1EB00C7A1EE078D2006CA180 /* LayerContactSheet.ofx */,
1E89B5771D81A7C000F61E6B /* Log2Lin.ofx */,
1E2D33DB1C3FB9A3004E2F03 /* MatteMonitor.ofx */,
D74121D418F9CF3D00A81F8B /* Merge.ofx */,
@@ -8244,6 +8316,7 @@
1E8B5D6818B76F8700C31FDC /* ColorLookup.cpp in Sources */,
1EAFE3E71C5D092900F9E4E4 /* ColorSuppress.cpp in Sources */,
1ED537371A234D3C007966D5 /* ColorTransform.cpp in Sources */,
+ 1EB00C9C1EE07A55006CA180 /* LayerContactSheet.cpp in Sources */,
1EE7A8CB1C74B909001AE4BC /* ColorWheel.cpp in Sources */,
D74A80C719405A14007C3E1C /* Crop.cpp in Sources */,
1E92573819EC1E140018F19A /* Clamp.cpp in Sources */,
@@ -8476,6 +8549,28 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 1EB00C7B1EE078D2006CA180 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1EB00C931EE0792A006CA180 /* ofxsOGLFontData.cpp in Sources */,
+ 1EB00C951EE0792A006CA180 /* ofxsOGLTextRenderer.cpp in Sources */,
+ 1EB00C7D1EE078D2006CA180 /* ofxsCore.cpp in Sources */,
+ 1EB00C9B1EE07A53006CA180 /* LayerContactSheet.cpp in Sources */,
+ 1EB00C7E1EE078D2006CA180 /* tinythread.cpp in Sources */,
+ 1EB00C7F1EE078D2006CA180 /* ofxsImageEffect.cpp in Sources */,
+ 1EB00C801EE078D2006CA180 /* ofxsInteract.cpp in Sources */,
+ 1EB00C811EE078D2006CA180 /* ofxsGenerator.cpp in Sources */,
+ 1EB00C821EE078D2006CA180 /* ofxsLog.cpp in Sources */,
+ 1EB00C831EE078D2006CA180 /* ofxsThreadSuite.cpp in Sources */,
+ 1EB00C841EE078D2006CA180 /* ofxsMultiThread.cpp in Sources */,
+ 1EB00C851EE078D2006CA180 /* ofxsParams.cpp in Sources */,
+ 1EB00C861EE078D2006CA180 /* ofxsProperty.cpp in Sources */,
+ 1EB00C871EE078D2006CA180 /* ofxsPropertyValidation.cpp in Sources */,
+ 1EB00C881EE078D2006CA180 /* ofxsRectangleInteract.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
1EB0A4611AA202EC00F9C93E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -10578,6 +10673,28 @@
};
name = Release;
};
+ 1EB00C8F1EE078D2006CA180 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ EXPORTED_SYMBOLS_FILE = "$(OFX_PATH)/Support/include/osxSymbols";
+ INFOPLIST_FILE = LayerContactSheet/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/OFX/Plugins/$(PROJECT_NAME)";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WRAPPER_EXTENSION = bundle;
+ };
+ name = Debug;
+ };
+ 1EB00C901EE078D2006CA180 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ EXPORTED_SYMBOLS_FILE = "$(OFX_PATH)/Support/include/osxSymbols";
+ INFOPLIST_FILE = LayerContactSheet/Info.plist;
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/OFX/Plugins/$(PROJECT_NAME)";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WRAPPER_EXTENSION = bundle;
+ };
+ name = Release;
+ };
1EB0A4761AA202EC00F9C93E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -12082,6 +12199,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 1EB00C8E1EE078D2006CA180 /* Build configuration list for PBXNativeTarget "LayerContactSheet.ofx" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1EB00C8F1EE078D2006CA180 /* Debug */,
+ 1EB00C901EE078D2006CA180 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
1EB0A4751AA202EC00F9C93E /* Build configuration list for PBXNativeTarget "Position.ofx" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/Misc/Makefile b/Misc/Makefile
index cc631a876..f8c240d7e 100644
--- a/Misc/Makefile
+++ b/Misc/Makefile
@@ -54,6 +54,7 @@ Invert.o \
JoinViews.o \
Keyer.o \
KeyMix.o \
+LayerContactSheet.o \
Log2Lin.o \
MatteMonitor.o \
Merge.o \
@@ -284,6 +285,7 @@ $(TOP_SRCDIR)/Invert \
$(TOP_SRCDIR)/JoinViews \
$(TOP_SRCDIR)/Keyer \
$(TOP_SRCDIR)/KeyMix \
+$(TOP_SRCDIR)/LayerContactSheet \
$(TOP_SRCDIR)/Log2Lin \
$(TOP_SRCDIR)/MatteMonitor \
$(TOP_SRCDIR)/Merge \
@@ -363,6 +365,7 @@ CXXFLAGS += \
-I$(TOP_SRCDIR)/Keyer \
-I$(TOP_SRCDIR)/KeyMix \
-I$(TOP_SRCDIR)/Log2Lin \
+-I$(TOP_SRCDIR)/LayerContactSheet \
-I$(TOP_SRCDIR)/MatteMonitor \
-I$(TOP_SRCDIR)/Merge \
-I$(TOP_SRCDIR)/Mirror \
diff --git a/Misc/Misc.vcxproj b/Misc/Misc.vcxproj
index c291b5b53..10e58d7ff 100644
--- a/Misc/Misc.vcxproj
+++ b/Misc/Misc.vcxproj
@@ -81,7 +81,7 @@
Level3
Disabled
- $(SolutionDir)..\openfx\include;$(SolutionDir)..\openfx\Support\include;$(SolutionDir)..\openfx\Support\Plugins\include;$(SolutionDir)..\Distortion;$(SolutionDir)..\Position;$(SolutionDir)..\FrameBlend;$(SolutionDir)..\FrameHold;$(SolutionDir)..\FrameRange;$(SolutionDir)..\Test;$(SolutionDir)..\AppendClip;$(SolutionDir)..\Mirror;$(SolutionDir)..\CheckerBoard;$(SolutionDir)..\ImageStatistics;$(SolutionDir)..\Radial;$(SolutionDir)..\Rectangle;$(SolutionDir)..\Clamp;$(SolutionDir)..\GodRays;$(SolutionDir)..\Saturation;$(SolutionDir)..\Switch;$(SolutionDir)..\TimeOffset;$(SolutionDir)..\ColorLookup;$(SolutionDir)..\SideBySide;$(SolutionDir)..\SlitScan;$(SolutionDir)..\MatteMonitor;$(SolutionDir)..\MixViews;$(SolutionDir)..\OneView;$(SolutionDir)..\JoinViews;$(SolutionDir)..\Anaglyph;$(SolutionDir)..\ColorCorrect;$(SolutionDir)..\Grade;$(SolutionDir)..\Transform;$(SolutionDir)..\Merge;$(SolutionDir)..\ChromaKeyer;$(SolutionDir)..\Roto;$(SolutionDir)..\CornerPin;$(SolutionDir);$(SolutionDir)..\Crop;$(SolutionDir)..\CopyRectangle;$(SolutionDir)..\Invert;$(SolutionDir)..\ReConverge;$(SolutionDir)..\Shuffle;$(SolutionDir)..\Difference;$(SolutionDir)..\Constant;$(SolutionDir)..\ContactSheet;$(SolutionDir)..\Premult;$(SolutionDir)..\TrackerPM;$(SolutionDir)..\NoOp;$(SolutionDir)..\Noise;$(SolutionDir)..\SupportExt;$(SolutionDir)..\ColorMatrix;$(SolutionDir)..\ColorSuppress;$(SolutionDir)..\Deinterlace;$(SolutionDir)..\Despill;$(SolutionDir)..\Dissolve;$(SolutionDir)..\Retime;$(SolutionDir)..\HSVTool;$(SolutionDir)..\VectorToColor;$(SolutionDir)..\ColorTransform;$(SolutionDir)..\Multiply;$(SolutionDir)..\Gamma;$(SolutionDir)..\ClipTest;$(SolutionDir)..\TimeBuffer;$(SolutionDir)..\Add;$(SolutionDir)..\Keyer;$(SolutionDir)..\TimeBlur;%(AdditionalIncludeDirectories)
+ $(SolutionDir)..\openfx\include;$(SolutionDir)..\openfx\Support\include;$(SolutionDir)..\openfx\Support\Plugins\include;$(SolutionDir)..\Distortion;$(SolutionDir)..\Position;$(SolutionDir)..\FrameBlend;$(SolutionDir)..\FrameHold;$(SolutionDir)..\FrameRange;$(SolutionDir)..\Test;$(SolutionDir)..\AppendClip;$(SolutionDir)..\Mirror;$(SolutionDir)..\CheckerBoard;$(SolutionDir)..\ImageStatistics;$(SolutionDir)..\Radial;$(SolutionDir)..\Rectangle;$(SolutionDir)..\Clamp;$(SolutionDir)..\GodRays;$(SolutionDir)..\Saturation;$(SolutionDir)..\Switch;$(SolutionDir)..\TimeOffset;$(SolutionDir)..\ColorLookup;$(SolutionDir)..\SideBySide;$(SolutionDir)..\SlitScan;$(SolutionDir)..\MatteMonitor;$(SolutionDir)..\MixViews;$(SolutionDir)..\OneView;$(SolutionDir)..\JoinViews;$(SolutionDir)..\Anaglyph;$(SolutionDir)..\ColorCorrect;$(SolutionDir)..\Grade;$(SolutionDir)..\Transform;$(SolutionDir)..\Merge;$(SolutionDir)..\ChromaKeyer;$(SolutionDir)..\Roto;$(SolutionDir)..\CornerPin;$(SolutionDir);$(SolutionDir)..\Crop;$(SolutionDir)..\CopyRectangle;$(SolutionDir)..\Invert;$(SolutionDir)..\ReConverge;$(SolutionDir)..\Shuffle;$(SolutionDir)..\Difference;$(SolutionDir)..\Constant;$(SolutionDir)..\ContactSheet;$(SolutionDir)..\LayerContactSheet;$(SolutionDir)..\Premult;$(SolutionDir)..\TrackerPM;$(SolutionDir)..\NoOp;$(SolutionDir)..\Noise;$(SolutionDir)..\SupportExt;$(SolutionDir)..\ColorMatrix;$(SolutionDir)..\ColorSuppress;$(SolutionDir)..\Deinterlace;$(SolutionDir)..\Despill;$(SolutionDir)..\Dissolve;$(SolutionDir)..\Retime;$(SolutionDir)..\HSVTool;$(SolutionDir)..\VectorToColor;$(SolutionDir)..\ColorTransform;$(SolutionDir)..\Multiply;$(SolutionDir)..\Gamma;$(SolutionDir)..\ClipTest;$(SolutionDir)..\TimeBuffer;$(SolutionDir)..\Add;$(SolutionDir)..\Keyer;$(SolutionDir)..\TimeBlur;%(AdditionalIncludeDirectories)
OFX_EXTENSIONS_VEGAS;OFX_EXTENSIONS_TUTTLE;OFX_EXTENSIONS_NUKE;OFX_EXTENSIONS_NATRON;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;WIN32;NOMINMAX;%(PreprocessorDefinitions)
@@ -161,7 +161,7 @@ xcopy $(SolutionDir)..\VectorToColor\net.sf.openfx.VectorToColorPlugin.png $(Out
Level3
Disabled
- $(SolutionDir)..\openfx\include;$(SolutionDir)..\openfx\Support\include;$(SolutionDir)..\openfx\Support\Plugins\include;$(SolutionDir)..\Distortion;$(SolutionDir)..\Position;$(SolutionDir)..\FrameBlend;$(SolutionDir)..\FrameHold;$(SolutionDir)..\FrameRange;$(SolutionDir)..\Test;$(SolutionDir)..\AppendClip;$(SolutionDir)..\Mirror;$(SolutionDir)..\CheckerBoard;$(SolutionDir)..\ImageStatistics;$(SolutionDir)..\Radial;$(SolutionDir)..\Rectangle;$(SolutionDir)..\Clamp;$(SolutionDir)..\GodRays;$(SolutionDir)..\Saturation;$(SolutionDir)..\Switch;$(SolutionDir)..\TimeOffset;$(SolutionDir)..\ColorLookup;$(SolutionDir)..\SideBySide;$(SolutionDir)..\SlitScan;$(SolutionDir)..\MatteMonitor;$(SolutionDir)..\MixViews;$(SolutionDir)..\OneView;$(SolutionDir)..\JoinViews;$(SolutionDir)..\Anaglyph;$(SolutionDir)..\ColorCorrect;$(SolutionDir)..\Grade;$(SolutionDir)..\Transform;$(SolutionDir)..\Merge;$(SolutionDir)..\ChromaKeyer;$(SolutionDir)..\Roto;$(SolutionDir)..\CornerPin;$(SolutionDir);$(SolutionDir)..\Crop;$(SolutionDir)..\CopyRectangle;$(SolutionDir)..\Invert;$(SolutionDir)..\ReConverge;$(SolutionDir)..\Shuffle;$(SolutionDir)..\Difference;$(SolutionDir)..\Constant;$(SolutionDir)..\ContactSheet;$(SolutionDir)..\Premult;$(SolutionDir)..\TrackerPM;$(SolutionDir)..\NoOp;$(SolutionDir)..\Noise;$(SolutionDir)..\SupportExt;$(SolutionDir)..\ColorMatrix;$(SolutionDir)..\ColorSuppress;$(SolutionDir)..\Deinterlace;$(SolutionDir)..\Despill;$(SolutionDir)..\Dissolve;$(SolutionDir)..\Retime;$(SolutionDir)..\HSVTool;$(SolutionDir)..\VectorToColor;$(SolutionDir)..\ColorTransform;$(SolutionDir)..\Multiply;$(SolutionDir)..\Gamma;$(SolutionDir)..\ClipTest;$(SolutionDir)..\TimeBuffer;$(SolutionDir)..\Add;$(SolutionDir)..\Keyer;$(SolutionDir)..\TimeBlur;$(SolutionDir)..\AdjustRoD;$(SolutionDir)..\Ramp;%(AdditionalIncludeDirectories)
+ $(SolutionDir)..\openfx\include;$(SolutionDir)..\openfx\Support\include;$(SolutionDir)..\openfx\Support\Plugins\include;$(SolutionDir)..\Distortion;$(SolutionDir)..\Position;$(SolutionDir)..\FrameBlend;$(SolutionDir)..\FrameHold;$(SolutionDir)..\FrameRange;$(SolutionDir)..\Test;$(SolutionDir)..\AppendClip;$(SolutionDir)..\Mirror;$(SolutionDir)..\CheckerBoard;$(SolutionDir)..\ImageStatistics;$(SolutionDir)..\Radial;$(SolutionDir)..\Rectangle;$(SolutionDir)..\Clamp;$(SolutionDir)..\GodRays;$(SolutionDir)..\Saturation;$(SolutionDir)..\Switch;$(SolutionDir)..\TimeOffset;$(SolutionDir)..\ColorLookup;$(SolutionDir)..\SideBySide;$(SolutionDir)..\SlitScan;$(SolutionDir)..\MatteMonitor;$(SolutionDir)..\MixViews;$(SolutionDir)..\OneView;$(SolutionDir)..\JoinViews;$(SolutionDir)..\Anaglyph;$(SolutionDir)..\ColorCorrect;$(SolutionDir)..\Grade;$(SolutionDir)..\Transform;$(SolutionDir)..\Merge;$(SolutionDir)..\ChromaKeyer;$(SolutionDir)..\Roto;$(SolutionDir)..\CornerPin;$(SolutionDir);$(SolutionDir)..\Crop;$(SolutionDir)..\CopyRectangle;$(SolutionDir)..\Invert;$(SolutionDir)..\ReConverge;$(SolutionDir)..\Shuffle;$(SolutionDir)..\Difference;$(SolutionDir)..\Constant;$(SolutionDir)..\ContactSheet;$(SolutionDir)..\LayerContactSheet;$(SolutionDir)..\Premult;$(SolutionDir)..\TrackerPM;$(SolutionDir)..\NoOp;$(SolutionDir)..\Noise;$(SolutionDir)..\SupportExt;$(SolutionDir)..\ColorMatrix;$(SolutionDir)..\ColorSuppress;$(SolutionDir)..\Deinterlace;$(SolutionDir)..\Despill;$(SolutionDir)..\Dissolve;$(SolutionDir)..\Retime;$(SolutionDir)..\HSVTool;$(SolutionDir)..\VectorToColor;$(SolutionDir)..\ColorTransform;$(SolutionDir)..\Multiply;$(SolutionDir)..\Gamma;$(SolutionDir)..\ClipTest;$(SolutionDir)..\TimeBuffer;$(SolutionDir)..\Add;$(SolutionDir)..\Keyer;$(SolutionDir)..\TimeBlur;$(SolutionDir)..\AdjustRoD;$(SolutionDir)..\Ramp;%(AdditionalIncludeDirectories)
OFX_EXTENSIONS_VEGAS;OFX_EXTENSIONS_TUTTLE;OFX_EXTENSIONS_NUKE;OFX_EXTENSIONS_NATRON;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;WIN64;NOMINMAX;%(PreprocessorDefinitions)
MultiThreaded
@@ -245,7 +245,7 @@ xcopy $(SolutionDir)..\VectorToColor\net.sf.openfx.VectorToColorPlugin.png $(Out
true
true
OFX_EXTENSIONS_VEGAS;OFX_EXTENSIONS_TUTTLE;OFX_EXTENSIONS_NUKE;OFX_EXTENSIONS_NATRON;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;WIN32;NOMINMAX;NDEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)..\openfx\include;$(SolutionDir)..\openfx\Support\include;$(SolutionDir)..\openfx\Support\Plugins\include;$(SolutionDir)..\Distortion;$(SolutionDir)..\Position;$(SolutionDir)..\FrameBlend;$(SolutionDir)..\FrameHold;$(SolutionDir)..\FrameRange;$(SolutionDir)..\Test;$(SolutionDir)..\AppendClip;$(SolutionDir)..\Mirror;$(SolutionDir)..\CheckerBoard;$(SolutionDir)..\ImageStatistics;$(SolutionDir)..\Radial;$(SolutionDir)..\Rectangle;$(SolutionDir)..\Clamp;$(SolutionDir)..\GodRays;$(SolutionDir)..\Saturation;$(SolutionDir)..\Switch;$(SolutionDir)..\TimeOffset;$(SolutionDir)..\ColorLookup;$(SolutionDir)..\SideBySide;$(SolutionDir)..\SlitScan;$(SolutionDir)..\MatteMonitor;$(SolutionDir)..\MixViews;$(SolutionDir)..\OneView;$(SolutionDir)..\JoinViews;$(SolutionDir)..\Anaglyph;$(SolutionDir)..\ColorCorrect;$(SolutionDir)..\Grade;$(SolutionDir)..\Transform;$(SolutionDir)..\Merge;$(SolutionDir)..\ChromaKeyer;$(SolutionDir)..\Roto;$(SolutionDir)..\CornerPin;$(SolutionDir);$(SolutionDir)..\Crop;$(SolutionDir)..\CopyRectangle;$(SolutionDir)..\Invert;$(SolutionDir)..\ReConverge;$(SolutionDir)..\Shuffle;$(SolutionDir)..\Difference;$(SolutionDir)..\Constant;$(SolutionDir)..\ContactSheet;$(SolutionDir)..\Premult;$(SolutionDir)..\TrackerPM;$(SolutionDir)..\NoOp;$(SolutionDir)..\Noise;$(SolutionDir)..\SupportExt;$(SolutionDir)..\ColorMatrix;$(SolutionDir)..\ColorSuppress;$(SolutionDir)..\Deinterlace;$(SolutionDir)..\Despill;$(SolutionDir)..\Dissolve;$(SolutionDir)..\Retime;$(SolutionDir)..\HSVTool;$(SolutionDir)..\VectorToColor;$(SolutionDir)..\ColorTransform;$(SolutionDir)..\Multiply;$(SolutionDir)..\Gamma;$(SolutionDir)..\ClipTest;$(SolutionDir)..\TimeBuffer;$(SolutionDir)..\Add;$(SolutionDir)..\Keyer;$(SolutionDir)..\TimeBlur;$(SolutionDir)..\AdjustRoD;$(SolutionDir)..\Ramp;%(AdditionalIncludeDirectories)
+ $(SolutionDir)..\openfx\include;$(SolutionDir)..\openfx\Support\include;$(SolutionDir)..\openfx\Support\Plugins\include;$(SolutionDir)..\Distortion;$(SolutionDir)..\Position;$(SolutionDir)..\FrameBlend;$(SolutionDir)..\FrameHold;$(SolutionDir)..\FrameRange;$(SolutionDir)..\Test;$(SolutionDir)..\AppendClip;$(SolutionDir)..\Mirror;$(SolutionDir)..\CheckerBoard;$(SolutionDir)..\ImageStatistics;$(SolutionDir)..\Radial;$(SolutionDir)..\Rectangle;$(SolutionDir)..\Clamp;$(SolutionDir)..\GodRays;$(SolutionDir)..\Saturation;$(SolutionDir)..\Switch;$(SolutionDir)..\TimeOffset;$(SolutionDir)..\ColorLookup;$(SolutionDir)..\SideBySide;$(SolutionDir)..\SlitScan;$(SolutionDir)..\MatteMonitor;$(SolutionDir)..\MixViews;$(SolutionDir)..\OneView;$(SolutionDir)..\JoinViews;$(SolutionDir)..\Anaglyph;$(SolutionDir)..\ColorCorrect;$(SolutionDir)..\Grade;$(SolutionDir)..\Transform;$(SolutionDir)..\Merge;$(SolutionDir)..\ChromaKeyer;$(SolutionDir)..\Roto;$(SolutionDir)..\CornerPin;$(SolutionDir);$(SolutionDir)..\Crop;$(SolutionDir)..\CopyRectangle;$(SolutionDir)..\Invert;$(SolutionDir)..\ReConverge;$(SolutionDir)..\Shuffle;$(SolutionDir)..\Difference;$(SolutionDir)..\Constant;$(SolutionDir)..\ContactSheet;$(SolutionDir)..\LayerContactSheet;$(SolutionDir)..\Premult;$(SolutionDir)..\TrackerPM;$(SolutionDir)..\NoOp;$(SolutionDir)..\Noise;$(SolutionDir)..\SupportExt;$(SolutionDir)..\ColorMatrix;$(SolutionDir)..\ColorSuppress;$(SolutionDir)..\Deinterlace;$(SolutionDir)..\Despill;$(SolutionDir)..\Dissolve;$(SolutionDir)..\Retime;$(SolutionDir)..\HSVTool;$(SolutionDir)..\VectorToColor;$(SolutionDir)..\ColorTransform;$(SolutionDir)..\Multiply;$(SolutionDir)..\Gamma;$(SolutionDir)..\ClipTest;$(SolutionDir)..\TimeBuffer;$(SolutionDir)..\Add;$(SolutionDir)..\Keyer;$(SolutionDir)..\TimeBlur;$(SolutionDir)..\AdjustRoD;$(SolutionDir)..\Ramp;%(AdditionalIncludeDirectories)
MultiThreaded
@@ -331,7 +331,7 @@ xcopy $(SolutionDir)..\VectorToColor\net.sf.openfx.VectorToColorPlugin.png $(Out
true
true
OFX_EXTENSIONS_VEGAS;OFX_EXTENSIONS_TUTTLE;OFX_EXTENSIONS_NUKE;OFX_EXTENSIONS_NATRON;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;WIN64;NOMINMAX;NDEBUG;%(PreprocessorDefinitions)
- $(SolutionDir)..\openfx\include;$(SolutionDir)..\openfx\Support\include;$(SolutionDir)..\openfx\Support\Plugins\include;$(SolutionDir)..\Distortion;$(SolutionDir)..\Position;$(SolutionDir)..\FrameBlend;$(SolutionDir)..\FrameHold;$(SolutionDir)..\FrameRange;$(SolutionDir)..\Test;$(SolutionDir)..\AppendClip;$(SolutionDir)..\Mirror;$(SolutionDir)..\CheckerBoard;$(SolutionDir)..\ImageStatistics;$(SolutionDir)..\Radial;$(SolutionDir)..\Rectangle;$(SolutionDir)..\Clamp;$(SolutionDir)..\GodRays;$(SolutionDir)..\Saturation;$(SolutionDir)..\Switch;$(SolutionDir)..\TimeOffset;$(SolutionDir)..\ColorLookup;$(SolutionDir)..\SideBySide;$(SolutionDir)..\SlitScan;$(SolutionDir)..\MatteMonitor;$(SolutionDir)..\MixViews;$(SolutionDir)..\OneView;$(SolutionDir)..\JoinViews;$(SolutionDir)..\Anaglyph;$(SolutionDir)..\ColorCorrect;$(SolutionDir)..\Grade;$(SolutionDir)..\Transform;$(SolutionDir)..\Merge;$(SolutionDir)..\ChromaKeyer;$(SolutionDir)..\Roto;$(SolutionDir)..\CornerPin;$(SolutionDir);$(SolutionDir)..\Crop;$(SolutionDir)..\CopyRectangle;$(SolutionDir)..\Invert;$(SolutionDir)..\ReConverge;$(SolutionDir)..\Shuffle;$(SolutionDir)..\Difference;$(SolutionDir)..\Constant;$(SolutionDir)..\ContactSheet;$(SolutionDir)..\Premult;$(SolutionDir)..\TrackerPM;$(SolutionDir)..\NoOp;$(SolutionDir)..\Noise;$(SolutionDir)..\SupportExt;$(SolutionDir)..\ColorMatrix;$(SolutionDir)..\ColorSuppress;$(SolutionDir)..\Deinterlace;$(SolutionDir)..\Despill;$(SolutionDir)..\Dissolve;$(SolutionDir)..\Retime;$(SolutionDir)..\HSVTool;$(SolutionDir)..\VectorToColor;$(SolutionDir)..\ColorTransform;$(SolutionDir)..\Multiply;$(SolutionDir)..\Gamma;$(SolutionDir)..\ClipTest;$(SolutionDir)..\TimeBuffer;$(SolutionDir)..\Add;$(SolutionDir)..\Keyer;$(SolutionDir)..\TimeBlur;$(SolutionDir)..\AdjustRoD;$(SolutionDir)..\Ramp;%(AdditionalIncludeDirectories)
+ $(SolutionDir)..\openfx\include;$(SolutionDir)..\openfx\Support\include;$(SolutionDir)..\openfx\Support\Plugins\include;$(SolutionDir)..\Distortion;$(SolutionDir)..\Position;$(SolutionDir)..\FrameBlend;$(SolutionDir)..\FrameHold;$(SolutionDir)..\FrameRange;$(SolutionDir)..\Test;$(SolutionDir)..\AppendClip;$(SolutionDir)..\Mirror;$(SolutionDir)..\CheckerBoard;$(SolutionDir)..\ImageStatistics;$(SolutionDir)..\Radial;$(SolutionDir)..\Rectangle;$(SolutionDir)..\Clamp;$(SolutionDir)..\GodRays;$(SolutionDir)..\Saturation;$(SolutionDir)..\Switch;$(SolutionDir)..\TimeOffset;$(SolutionDir)..\ColorLookup;$(SolutionDir)..\SideBySide;$(SolutionDir)..\SlitScan;$(SolutionDir)..\MatteMonitor;$(SolutionDir)..\MixViews;$(SolutionDir)..\OneView;$(SolutionDir)..\JoinViews;$(SolutionDir)..\Anaglyph;$(SolutionDir)..\ColorCorrect;$(SolutionDir)..\Grade;$(SolutionDir)..\Transform;$(SolutionDir)..\Merge;$(SolutionDir)..\ChromaKeyer;$(SolutionDir)..\Roto;$(SolutionDir)..\CornerPin;$(SolutionDir);$(SolutionDir)..\Crop;$(SolutionDir)..\CopyRectangle;$(SolutionDir)..\Invert;$(SolutionDir)..\ReConverge;$(SolutionDir)..\Shuffle;$(SolutionDir)..\Difference;$(SolutionDir)..\Constant;$(SolutionDir)..\ContactSheet;$(SolutionDir)..\LayerContactSheet;$(SolutionDir)..\Premult;$(SolutionDir)..\TrackerPM;$(SolutionDir)..\NoOp;$(SolutionDir)..\Noise;$(SolutionDir)..\SupportExt;$(SolutionDir)..\ColorMatrix;$(SolutionDir)..\ColorSuppress;$(SolutionDir)..\Deinterlace;$(SolutionDir)..\Despill;$(SolutionDir)..\Dissolve;$(SolutionDir)..\Retime;$(SolutionDir)..\HSVTool;$(SolutionDir)..\VectorToColor;$(SolutionDir)..\ColorTransform;$(SolutionDir)..\Multiply;$(SolutionDir)..\Gamma;$(SolutionDir)..\ClipTest;$(SolutionDir)..\TimeBuffer;$(SolutionDir)..\Add;$(SolutionDir)..\Keyer;$(SolutionDir)..\TimeBlur;$(SolutionDir)..\AdjustRoD;$(SolutionDir)..\Ramp;%(AdditionalIncludeDirectories)
MultiThreaded
@@ -446,6 +446,7 @@ xcopy $(SolutionDir)..\VectorToColor\net.sf.openfx.VectorToColorPlugin.png $(Out
+
diff --git a/README.md b/README.md
index 66bc58365..c70da7b55 100644
--- a/README.md
+++ b/README.md
@@ -153,6 +153,7 @@ grouping).
* CopyRectangleOFX: Copies a rectangle from the input A to the input B in output.
* DissolveOFX: Weighted average of two inputs.
* KeyMixOFX: Copies A to B only where Mask is non-zero.
+* LayerContactSheetOFX: Make a contact sheet from layers.
* MergeOFX: Pixel-by-pixel merge operation between the two inputs.
* PreMultOFX/UnpremultOFX: Multiply/divide the selected channels by alpha (or another channel).
* SwitchOFX: Lets you switch between any number of inputs.