From 29872ced41513317509d0503bc87e16f99db1aed Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Sun, 27 Sep 2015 17:35:23 +0200
Subject: [PATCH 001/178] Fix crash in upscaleMipMapForDepth
---
Engine/Image.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Engine/Image.cpp b/Engine/Image.cpp
index b28f02338c..6953e08757 100644
--- a/Engine/Image.cpp
+++ b/Engine/Image.cpp
@@ -1740,13 +1740,15 @@ Image::upscaleMipMapForDepth(const RectI & roi,
PIX * dstPixFirst = dstLineBatchStart;
// fill the first line
for (int xo = dstRoi.x1; xo < dstRoi.x2; ++xi, srcPix += components, xo += xcount, dstPixFirst += xcount * components) {
- xcount = scale + xo - xi * scale;
+ xcount = scale - (xo - xi * scale);
+ xcount = std::min(xcount, dstRoi.x2 - xo);
//assert(0 < xcount && xcount <= scale);
// replicate srcPix as many times as necessary
PIX * dstPix = dstPixFirst;
//assert((srcPix-(PIX*)pixelAt(srcRoi.x1, srcRoi.y1)) % components == 0);
for (int i = 0; i < xcount; ++i, dstPix += components) {
assert( ( dstPix - (PIX*)output->pixelAt(dstRoi.x1, dstRoi.y1) ) % components == 0 );
+ assert(dstPix >= (PIX*)output->pixelAt(xo, yo) && dstPix < (PIX*)output->pixelAt(xo, yo) + xcount * components);
for (int c = 0; c < components; ++c) {
dstPix[c] = srcPix[c];
}
From d270d8cde567bfb1fca4c59cf230b1d07fc5f42c Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Sun, 27 Sep 2015 17:59:39 +0200
Subject: [PATCH 002/178] RenderRoi: bug fix with render scale support = 0
---
Engine/EffectInstanceRenderRoI.cpp | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/Engine/EffectInstanceRenderRoI.cpp b/Engine/EffectInstanceRenderRoI.cpp
index 31dab7baba..91e05c56c2 100644
--- a/Engine/EffectInstanceRenderRoI.cpp
+++ b/Engine/EffectInstanceRenderRoI.cpp
@@ -818,7 +818,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
#if NATRON_ENABLE_TRIMAP
if (!frameRenderArgs.canAbort && frameRenderArgs.isRenderResponseToUserInteraction) {
#ifndef DEBUG
- isPlaneCached->getRestToRender_trimap(roi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
+ isPlaneCached->getRestToRender_trimap(upscaledRoi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
#else
// in debug mode, check that the result of getRestToRender_trimap and getRestToRender is the same if the image
// is not currently rendered concurrently
@@ -832,9 +832,9 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
}
if (!ibr) {
Image::ReadAccess racc( isPlaneCached.get() );
- isPlaneCached->getRestToRender_trimap(roi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
+ isPlaneCached->getRestToRender_trimap(upscaledRoi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
std::list tmpRects;
- isPlaneCached->getRestToRender(roi, tmpRects);
+ isPlaneCached->getRestToRender(upscaledRoi, tmpRects);
//If it crashes here that means the image is no longer being rendered but its bitmap still contains PIXEL_UNAVAILABLE pixels.
//The other thread should have removed that image from the cache or marked the image as rendered.
@@ -846,14 +846,14 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
assert(*it == *oIt);
}
} else {
- isPlaneCached->getRestToRender_trimap(roi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
+ isPlaneCached->getRestToRender_trimap(upscaledRoi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
}
#endif
} else {
- isPlaneCached->getRestToRender(roi, rectsLeftToRender);
+ isPlaneCached->getRestToRender(upscaledRoi, rectsLeftToRender);
}
#else
- isPlaneCached->getRestToRender(roi, rectsLeftToRender);
+ isPlaneCached->getRestToRender(upscaledRoi, rectsLeftToRender);
#endif
if ( isDuringPaintStroke && !rectsLeftToRender.empty() && !lastStrokePixelRoD.isNull() ) {
rectsLeftToRender.clear();
@@ -1404,9 +1404,11 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
for (std::map::iterator it = planesToRender.planes.begin(); it != planesToRender.planes.end(); ++it) {
//We have to return the downscale image, so make sure it has been computed
- if ( (renderRetCode != eRenderRoIStatusRenderFailed) && renderFullScaleThenDownscale && renderScaleOneUpstreamIfRenderScaleSupportDisabled ) {
+ if ( (renderRetCode != eRenderRoIStatusRenderFailed) &&
+ renderFullScaleThenDownscale &&
+ it->second.fullscaleImage->getMipMapLevel() != mipMapLevel &&
+ !hasSomethingToRender) {
assert(it->second.fullscaleImage->getMipMapLevel() == 0);
- roi.intersect(it->second.fullscaleImage->getBounds(), &roi);
if (it->second.downscaleImage == it->second.fullscaleImage) {
it->second.downscaleImage.reset( new Image(it->second.fullscaleImage->getComponents(),
it->second.fullscaleImage->getRoD(),
@@ -1417,7 +1419,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
false) );
}
- it->second.fullscaleImage->downscaleMipMap( it->second.fullscaleImage->getRoD(), roi, 0, args.mipMapLevel, false, it->second.downscaleImage.get() );
+ it->second.fullscaleImage->downscaleMipMap( it->second.fullscaleImage->getRoD(), upscaledRoi, 0, args.mipMapLevel, false, it->second.downscaleImage.get() );
}
///The image might need to be converted to fit the original requested format
bool imageConversionNeeded = it->first != it->second.downscaleImage->getComponents() || args.bitdepth != it->second.downscaleImage->getBitDepth();
From 3ecd1b28c8fe4ca3194cd1f71075a94be8555c4a Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Sun, 27 Sep 2015 20:46:43 +0200
Subject: [PATCH 003/178] Draft mode: only add to key if it is used by the
plug-in. Also cache image if render scale is not supported but inputs are
computed with mipmaplevel > 0 (just added a flag to the key for that)
---
Engine/EffectInstance.cpp | 221 ++++++++++-------------------
Engine/EffectInstance.h | 7 +-
Engine/EffectInstanceRenderRoI.cpp | 122 ++++++++--------
Engine/Image.cpp | 7 +-
Engine/Image.h | 3 +-
Engine/ImageKey.cpp | 12 +-
Engine/ImageKey.h | 7 +-
Engine/OfxEffectInstance.cpp | 6 +
Engine/OfxEffectInstance.h | 1 +
Engine/RotoContext.cpp | 2 +-
libs/OpenFX | 2 +-
11 files changed, 166 insertions(+), 224 deletions(-)
diff --git a/Engine/EffectInstance.cpp b/Engine/EffectInstance.cpp
index 501ff7ad6e..f654a41f90 100644
--- a/Engine/EffectInstance.cpp
+++ b/Engine/EffectInstance.cpp
@@ -1476,7 +1476,6 @@ EffectInstance::allocateImagePlane(const ImageKey & key,
double par,
unsigned int mipmapLevel,
bool renderFullScaleThenDownscale,
- bool renderScaleOneUpstreamIfRenderScaleSupportDisabled,
bool useDiskCache,
bool createInCache,
boost::shared_ptr* fullScaleImage,
@@ -1487,9 +1486,29 @@ EffectInstance::allocateImagePlane(const ImageKey & key,
//If we're rendering full scale and with input images at full scale, don't cache the downscale image since it is cheap to
//recreate, instead cache the full-scale image
- if (renderFullScaleThenDownscale && renderScaleOneUpstreamIfRenderScaleSupportDisabled) {
+ if (renderFullScaleThenDownscale) {
downscaleImage->reset( new Natron::Image(components, rod, downscaleImageBounds, mipmapLevel, par, depth, true) );
+ boost::shared_ptr upscaledImageParams = Natron::Image::makeParams(cost,
+ rod,
+ fullScaleImageBounds,
+ par,
+ 0,
+ isProjectFormat,
+ components,
+ depth,
+ framesNeeded);
+
+ //The upscaled image will be rendered with input images at full def, it is then the best possibly rendered image so cache it!
+
+ fullScaleImage->reset();
+ getOrCreateFromCacheInternal(key, upscaledImageParams, createInCache, useDiskCache, fullScaleImage);
+
+ if (!*fullScaleImage) {
+ return false;
+ }
+
} else {
+
///Cache the image with the requested components instead of the remapped ones
boost::shared_ptr cachedImgParams = Natron::Image::makeParams(cost,
rod,
@@ -1506,39 +1525,11 @@ EffectInstance::allocateImagePlane(const ImageKey & key,
///When calling allocateMemory() on the image, the cache already has the lock since it added it
///so taking this lock now ensures the image will be allocated completetly
- getOrCreateFromCacheInternal(key, cachedImgParams, createInCache, useDiskCache, fullScaleImage);
- if (!*fullScaleImage) {
+ getOrCreateFromCacheInternal(key, cachedImgParams, createInCache, useDiskCache, downscaleImage);
+ if (!*downscaleImage) {
return false;
}
-
-
- *downscaleImage = *fullScaleImage;
- }
-
- if (renderFullScaleThenDownscale) {
- if (!renderScaleOneUpstreamIfRenderScaleSupportDisabled) {
- ///The upscaled image will be rendered using input images at lower def... which means really crappy results, don't cache this image!
- fullScaleImage->reset( new Natron::Image(components, rod, fullScaleImageBounds, 0, par, depth, true) );
- } else {
- boost::shared_ptr upscaledImageParams = Natron::Image::makeParams(cost,
- rod,
- fullScaleImageBounds,
- par,
- 0,
- isProjectFormat,
- components,
- depth,
- framesNeeded);
-
- //The upscaled image will be rendered with input images at full def, it is then the best possibly rendered image so cache it!
-
- fullScaleImage->reset();
- getOrCreateFromCacheInternal(key, upscaledImageParams, createInCache, useDiskCache, fullScaleImage);
-
- if (!*fullScaleImage) {
- return false;
- }
- }
+ *fullScaleImage = *downscaleImage;
}
return true;
@@ -1650,7 +1641,6 @@ EffectInstance::tiledRenderingFunctor( TiledRenderingFunctorArgs & args,
specificData,
args.frameTLS,
args.renderFullScaleThenDownscale,
- args.renderUseScaleOneInputs,
args.isSequentialRender,
args.isRenderResponseToUserInteraction,
args.firstFrame,
@@ -1676,7 +1666,6 @@ EffectInstance::tiledRenderingFunctor(const QThread* callingThread,
const RectToRender & rectToRender,
const std::map, ParallelRenderArgs > & frameTLS,
bool renderFullScaleThenDownscale,
- bool renderUseScaleOneInputs,
bool isSequentialRender,
bool isRenderResponseToUserInteraction,
int firstFrame,
@@ -1697,8 +1686,6 @@ EffectInstance::tiledRenderingFunctor(const QThread* callingThread,
{
assert( !rectToRender.rect.isNull() );
- bool outputUseImage = renderFullScaleThenDownscale && renderUseScaleOneInputs;
-
///Make the thread-storage live as long as the render action is called if we're in a newly launched thread in eRenderSafetyFullySafeFrame mode
boost::shared_ptr scopedFrameArgs;
if ( !frameTLS.empty() && ( callingThread != QThread::currentThread() ) ) {
@@ -1725,7 +1712,8 @@ EffectInstance::tiledRenderingFunctor(const QThread* callingThread,
///Upscale the RoI to a region in the full scale image so it is in canonical coordinates
RectD canonicalRectToRender;
downscaledRectToRender.toCanonical(mipMapLevel, par, rod, &canonicalRectToRender);
- if ( !outputUseImage && (mipMapLevel > 0) && (renderMappedMipMapLevel != mipMapLevel) ) {
+ if (renderFullScaleThenDownscale) {
+ assert(mipMapLevel > 0 && renderMappedMipMapLevel != mipMapLevel);
canonicalRectToRender.toPixelEnclosing(renderMappedMipMapLevel, par, &renderMappedRectToRender);
}
@@ -1745,7 +1733,7 @@ EffectInstance::tiledRenderingFunctor(const QThread* callingThread,
// check the bitmap!
if (frameArgs.tilesSupported) {
- if (outputUseImage) {
+ if (renderFullScaleThenDownscale) {
//The renderMappedImage is cached , read bitmap from it
canonicalRectToRender.toPixelEnclosing(0, par, &downscaledRectToRender);
downscaledRectToRender.intersect(firstPlaneToRender.renderMappedImage->getBounds(), &downscaledRectToRender);
@@ -1786,28 +1774,15 @@ EffectInstance::tiledRenderingFunctor(const QThread* callingThread,
assert( downscaledRectToRenderMinimal.isNull() || (renderBounds.x1 <= downscaledRectToRenderMinimal.x1 && downscaledRectToRenderMinimal.x2 <= renderBounds.x2 &&
renderBounds.y1 <= downscaledRectToRenderMinimal.y1 && downscaledRectToRenderMinimal.y2 <= renderBounds.y2) );
-
-
- if (renderFullScaleThenDownscale) {
- ///If the new rect after getMinimalRect is bigger (maybe because another thread as grown the image)
- ///we stick to what was requested
- RectD canonicalrenderRectToRender;
- if ( downscaledRectToRender.contains(downscaledRectToRenderMinimal) ) {
- downscaledRectToRenderMinimal.toCanonical(mipMapLevel, par, rod, &canonicalrenderRectToRender);
- downscaledRectToRender = downscaledRectToRenderMinimal;
- } else {
- downscaledRectToRender.toCanonical(mipMapLevel, par, rod, &canonicalrenderRectToRender);
- }
- canonicalrenderRectToRender.toPixelEnclosing(0, par, &renderMappedRectToRender);
- renderMappedRectToRender.intersect(firstPlaneToRender.renderMappedImage->getBounds(), &renderMappedRectToRender);
- } else {
- ///If the new rect after getMinimalRect is bigger (maybe because another thread as grown the image)
- ///we stick to what was requested
- if ( downscaledRectToRender.contains(downscaledRectToRenderMinimal) ) {
- downscaledRectToRender = downscaledRectToRenderMinimal;
- renderMappedRectToRender = downscaledRectToRender;
- }
+
+
+ ///If the new rect after getMinimalRect is bigger (maybe because another thread as grown the image)
+ ///we stick to what was requested
+ if ( downscaledRectToRender.contains(downscaledRectToRenderMinimal) ) {
+ downscaledRectToRender = downscaledRectToRenderMinimal;
+ renderMappedRectToRender = downscaledRectToRender;
}
+
}
} // tilesSupported
///It might have been already rendered now
@@ -1871,7 +1846,6 @@ EffectInstance::tiledRenderingFunctor(const QThread* callingThread,
it != rectToRender.imgs.end();
++it) {
for (ImageList::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
- assert(outputUseImage || (*it2)->getMipMapLevel() == mipMapLevel);
const RectD & srcRodCanonical = (*it2)->getRoD();
RectI srcBounds;
srcRodCanonical.toPixelEnclosing( (*it2)->getMipMapLevel(), (*it2)->getPixelAspectRatio(), &srcBounds ); // compute srcRod at level 0
@@ -1935,7 +1909,6 @@ EffectInstance::tiledRenderingFunctor(const QThread* callingThread,
rectToRender.identityTime,
rectToRender.identityInput,
renderFullScaleThenDownscale,
- renderUseScaleOneInputs,
isSequentialRender,
isRenderResponseToUserInteraction,
renderMappedRectToRender,
@@ -1967,7 +1940,6 @@ EffectInstance::renderHandler(RenderArgs & args,
double identityTime,
Natron::EffectInstance* identityInput,
bool renderFullScaleThenDownscale,
- bool renderUseScaleOneInputs,
bool isSequentialRender,
bool isRenderResponseToUserInteraction,
const RectI & renderMappedRectToRender,
@@ -1999,7 +1971,6 @@ EffectInstance::renderHandler(RenderArgs & args,
renderBounds.y1 <= renderMappedRectToRender.y1 && renderMappedRectToRender.y2 <= renderBounds.y2);
# endif
- bool outputUseImage = renderUseScaleOneInputs && renderFullScaleThenDownscale;
RenderActionArgs actionArgs;
actionArgs.byPassCache = byPassCache;
for (int i = 0; i < 4; ++i) {
@@ -2037,7 +2008,7 @@ EffectInstance::renderHandler(RenderArgs & args,
this);
if (!identityInput) {
for (std::map::iterator it = planes.planes.begin(); it != planes.planes.end(); ++it) {
- if (outputUseImage) {
+ if (renderFullScaleThenDownscale) {
it->second.fullscaleImage->fillZero(downscaledRectToRender);
it->second.fullscaleImage->markForRendered(downscaledRectToRender);
} else {
@@ -2058,7 +2029,7 @@ EffectInstance::renderHandler(RenderArgs & args,
return eRenderingFunctorRetFailed;
} else if ( identityPlanes.empty() ) {
for (std::map::iterator it = planes.planes.begin(); it != planes.planes.end(); ++it) {
- if (outputUseImage) {
+ if (renderFullScaleThenDownscale) {
it->second.fullscaleImage->fillZero(downscaledRectToRender);
it->second.fullscaleImage->markForRendered(downscaledRectToRender);
} else {
@@ -2076,7 +2047,7 @@ EffectInstance::renderHandler(RenderArgs & args,
ImageList::iterator idIt = identityPlanes.begin();
for (std::map::iterator it = planes.planes.begin(); it != planes.planes.end(); ++it, ++idIt) {
- if ( outputUseImage && ( (*idIt)->getMipMapLevel() > it->second.fullscaleImage->getMipMapLevel() ) ) {
+ if ( renderFullScaleThenDownscale && ( (*idIt)->getMipMapLevel() > it->second.fullscaleImage->getMipMapLevel() ) ) {
if ( !(*idIt)->getBounds().contains(downscaledRectToRender) ) {
///Fill the RoI with 0's as the identity input image might have bounds contained into the RoI
it->second.fullscaleImage->fillZero(downscaledRectToRender);
@@ -2165,7 +2136,7 @@ EffectInstance::renderHandler(RenderArgs & args,
#if NATRON_ENABLE_TRIMAP
if (!frameArgs.canAbort && frameArgs.isRenderResponseToUserInteraction) {
for (std::map::iterator it = args._outputPlanes.begin(); it != args._outputPlanes.end(); ++it) {
- if (outputUseImage) {
+ if (renderFullScaleThenDownscale) {
it->second.fullscaleImage->markForRendering(downscaledRectToRender);
} else {
it->second.downscaleImage->markForRendering(downscaledRectToRender);
@@ -2225,7 +2196,7 @@ EffectInstance::renderHandler(RenderArgs & args,
using it while it has still pixels marked to PIXEL_UNAVAILABLE, hence clear the bitmap
*/
for (std::map::const_iterator it = outputPlanes.begin(); it != outputPlanes.end(); ++it) {
- if (outputUseImage) {
+ if (renderFullScaleThenDownscale) {
it->second.fullscaleImage->clearBitmap(downscaledRectToRender);
} else {
it->second.downscaleImage->clearBitmap(downscaledRectToRender);
@@ -2283,86 +2254,38 @@ EffectInstance::renderHandler(RenderArgs & args,
} else {
if (renderFullScaleThenDownscale) {
///copy the rectangle rendered in the full scale image to the downscaled output
-
- /* If we're using renderUseScaleOneInputs, the full scale image is cached.
- We might have been asked to render only a portion.
- Hence we're not sure that the whole part of the image will be downscaled.
- Instead we do all the downscale at once at the end of renderRoI().
- If !renderUseScaleOneInputs the image is not cached.
- Hence we know it will be rendered completly so it is safe to do this here and take advantage of the multi-threading.*/
- if ( (mipMapLevel != 0) && !renderUseScaleOneInputs ) {
- assert(it->second.fullscaleImage != it->second.downscaleImage && it->second.renderMappedImage == it->second.fullscaleImage);
-
-
- if ( ( it->second.downscaleImage->getComponents() != it->second.tmpImage->getComponents() ) ||
- ( it->second.downscaleImage->getBitDepth() != it->second.tmpImage->getBitDepth() ) ) {
- /*
- * BitDepth/Components conversion required as well as downscaling, do conversion to a tmp buffer
- */
- ImagePtr tmp( new Image(it->second.downscaleImage->getComponents(), it->second.tmpImage->getRoD(), it->second.tmpImage->getBounds(), mipMapLevel, it->second.tmpImage->getPixelAspectRatio(), it->second.downscaleImage->getBitDepth(), false) );
-
- it->second.tmpImage->convertToFormat( it->second.tmpImage->getBounds(),
- getApp()->getDefaultColorSpaceForBitDepth( it->second.tmpImage->getBitDepth() ),
- getApp()->getDefaultColorSpaceForBitDepth( it->second.downscaleImage->getBitDepth() ),
- -1, false, unPremultRequired, tmp.get() );
- tmp->downscaleMipMap( it->second.tmpImage->getRoD(),
- actionArgs.roi, 0, mipMapLevel, false, it->second.downscaleImage.get() );
- } else {
- /*
- * Downscaling required only
- */
- it->second.tmpImage->downscaleMipMap( it->second.tmpImage->getRoD(),
- actionArgs.roi, 0, mipMapLevel, false, it->second.downscaleImage.get() );
- }
-
- it->second.downscaleImage->copyUnProcessedChannels(downscaledRectToRender, planes.outputPremult, originalImagePremultiplication, processChannels, originalInputImage);
- if (useMaskMix) {
- it->second.downscaleImage->applyMaskMix(downscaledRectToRender, maskImage.get(), originalInputImage.get(), doMask, false, mix);
- }
- it->second.downscaleImage->markForRendered(downscaledRectToRender);
- } else { // if (mipMapLevel != 0 && !renderUseScaleOneInputs) {
- assert(it->second.renderMappedImage == it->second.fullscaleImage);
- if (it->second.tmpImage != it->second.renderMappedImage) {
- if ( ( it->second.fullscaleImage->getComponents() != it->second.tmpImage->getComponents() ) ||
- ( it->second.fullscaleImage->getBitDepth() != it->second.tmpImage->getBitDepth() ) ) {
- /*
- * BitDepth/Components conversion required
- */
-
- it->second.tmpImage->copyUnProcessedChannels(it->second.tmpImage->getBounds(), planes.outputPremult, originalImagePremultiplication, processChannels, originalInputImage);
- if (useMaskMix) {
- it->second.tmpImage->applyMaskMix(actionArgs.roi, maskImage.get(), originalInputImage.get(), doMask, false, mix);
- }
- it->second.tmpImage->convertToFormat( it->second.tmpImage->getBounds(),
- getApp()->getDefaultColorSpaceForBitDepth( it->second.tmpImage->getBitDepth() ),
- getApp()->getDefaultColorSpaceForBitDepth( it->second.fullscaleImage->getBitDepth() ),
- -1, false, unPremultRequired, it->second.fullscaleImage.get() );
- } else {
- /*
- * No conversion required, copy to output
- */
- int prefInput = getNode()->getPreferredInput();
- RectI roiPixel;
- ImagePtr originalInputImageFullScale;
- if (prefInput != -1) {
- originalInputImageFullScale = getImage(prefInput, time, actionArgs.mappedScale, view, NULL, originalInputImage->getComponents(), originalInputImage->getBitDepth(), originalInputImage->getPixelAspectRatio(), false, &roiPixel);
- }
-
-
- if (originalInputImageFullScale) {
- it->second.fullscaleImage->copyUnProcessedChannels(actionArgs.roi, planes.outputPremult, originalImagePremultiplication, processChannels, originalInputImageFullScale);
- if (useMaskMix) {
- ImagePtr originalMaskFullScale = getImage(getMaxInputCount() - 1, time, actionArgs.mappedScale, view, NULL, ImageComponents::getAlphaComponents(), originalInputImage->getBitDepth(), originalInputImage->getPixelAspectRatio(), false, &roiPixel);
- if (originalMaskFullScale) {
- it->second.fullscaleImage->applyMaskMix(actionArgs.roi, originalMaskFullScale.get(), originalInputImageFullScale.get(), doMask, false, mix);
- }
- }
- }
- it->second.fullscaleImage->pasteFrom(*it->second.tmpImage, actionArgs.roi, false);
- }
- }
- it->second.fullscaleImage->markForRendered(actionArgs.roi);
+ assert(mipMapLevel != 0);
+
+ assert(it->second.fullscaleImage != it->second.downscaleImage && it->second.renderMappedImage == it->second.fullscaleImage);
+
+
+ if ( ( it->second.downscaleImage->getComponents() != it->second.tmpImage->getComponents() ) ||
+ ( it->second.downscaleImage->getBitDepth() != it->second.tmpImage->getBitDepth() ) ) {
+ /*
+ * BitDepth/Components conversion required as well as downscaling, do conversion to a tmp buffer
+ */
+ ImagePtr tmp( new Image(it->second.downscaleImage->getComponents(), it->second.tmpImage->getRoD(), it->second.tmpImage->getBounds(), mipMapLevel, it->second.tmpImage->getPixelAspectRatio(), it->second.downscaleImage->getBitDepth(), false) );
+
+ it->second.tmpImage->convertToFormat( it->second.tmpImage->getBounds(),
+ getApp()->getDefaultColorSpaceForBitDepth( it->second.tmpImage->getBitDepth() ),
+ getApp()->getDefaultColorSpaceForBitDepth( it->second.downscaleImage->getBitDepth() ),
+ -1, false, unPremultRequired, tmp.get() );
+ tmp->downscaleMipMap( it->second.tmpImage->getRoD(),
+ actionArgs.roi, 0, mipMapLevel, false, it->second.downscaleImage.get() );
+ } else {
+ /*
+ * Downscaling required only
+ */
+ it->second.tmpImage->downscaleMipMap( it->second.tmpImage->getRoD(),
+ actionArgs.roi, 0, mipMapLevel, false, it->second.downscaleImage.get() );
+ }
+
+ it->second.downscaleImage->copyUnProcessedChannels(downscaledRectToRender, planes.outputPremult, originalImagePremultiplication, processChannels, originalInputImage);
+ if (useMaskMix) {
+ it->second.downscaleImage->applyMaskMix(downscaledRectToRender, maskImage.get(), originalInputImage.get(), doMask, false, mix);
}
+ it->second.fullscaleImage->markForRendered(renderMappedRectToRender);
+
} else { // if (renderFullScaleThenDownscale) {
///Copy the rectangle rendered in the downscaled image
if (it->second.tmpImage != it->second.downscaleImage) {
@@ -2428,7 +2351,7 @@ EffectInstance::allocateImagePlaneAndSetInThreadLocalStorage(const Natron::Image
const ImagePtr & img = firstPlane.fullscaleImage->usesBitMap() ? firstPlane.fullscaleImage : firstPlane.downscaleImage;
boost::shared_ptr params = img->getParams();
PlaneToRender p;
- bool ok = allocateImagePlane(img->getKey(), img->getRoD(), img->getBounds(), img->getBounds(), false, params->getFramesNeeded(), plane, img->getBitDepth(), img->getPixelAspectRatio(), img->getMipMapLevel(), false, false, false, useCache, &p.fullscaleImage, &p.downscaleImage);
+ bool ok = allocateImagePlane(img->getKey(), img->getRoD(), img->getBounds(), img->getBounds(), false, params->getFramesNeeded(), plane, img->getBitDepth(), img->getPixelAspectRatio(), img->getMipMapLevel(), false, false, useCache, &p.fullscaleImage, &p.downscaleImage);
if (!ok) {
return ImagePtr();
} else {
diff --git a/Engine/EffectInstance.h b/Engine/EffectInstance.h
index d471d61239..65f7e8b56e 100644
--- a/Engine/EffectInstance.h
+++ b/Engine/EffectInstance.h
@@ -1127,6 +1127,8 @@ class EffectInstance
/// should be set during effect initialization, but may also be set by the first getRegionOfDefinition with scale != 1 that succeeds
void setSupportsRenderScaleMaybe(EffectInstance::SupportsEnum s) const;
+ virtual bool supportsRenderQuality() const { return false; }
+
/**
* @brief Does this effect can support multiple clips PAR ?
* http://openfx.sourceforge.net/Documentation/1.3/ofxProgrammingReference.html#kOfxImageEffectPropSupportsMultipleClipPARs
@@ -1636,7 +1638,6 @@ class EffectInstance
bool isRenderMadeInResponseToUserInteraction,
U64 nodeHash,
bool renderFullScaleThenDownscale,
- bool useScaleOneInputImages,
bool byPassCache,
Natron::ImageBitDepthEnum outputClipPrefDepth,
const std::list & outputClipPrefsComps,
@@ -1694,7 +1695,6 @@ class EffectInstance
double par,
unsigned int mipmapLevel,
bool renderFullScaleThenDownscale,
- bool renderScaleOneUpstreamIfRenderScaleSupportDisabled,
bool useDiskCache,
bool createInCache,
boost::shared_ptr* fullScaleImage,
@@ -1725,7 +1725,6 @@ class EffectInstance
ParallelRenderArgs frameArgs;
std::map, ParallelRenderArgs > frameTLS;
bool renderFullScaleThenDownscale;
- bool renderUseScaleOneInputs;
bool isSequentialRender;
bool isRenderResponseToUserInteraction;
int firstFrame;
@@ -1753,7 +1752,6 @@ class EffectInstance
const RectToRender & rectToRender,
const std::map, ParallelRenderArgs > & frameTls,
bool renderFullScaleThenDownscale,
- bool renderUseScaleOneInputs,
bool isSequentialRender,
bool isRenderResponseToUserInteraction,
int firstFrame, int lastFrame,
@@ -1800,7 +1798,6 @@ class EffectInstance
double identityTime,
Natron::EffectInstance* identityInput,
bool renderFullScaleThenDownscale,
- bool renderUseScaleOneInputs,
bool isSequentialRender,
bool isRenderResponseToUserInteraction,
const RectI & renderMappedRectToRender,
diff --git a/Engine/EffectInstanceRenderRoI.cpp b/Engine/EffectInstanceRenderRoI.cpp
index 91e05c56c2..4d3f41341d 100644
--- a/Engine/EffectInstanceRenderRoI.cpp
+++ b/Engine/EffectInstanceRenderRoI.cpp
@@ -291,37 +291,18 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// End get RoD ///////////////////////////////////////////////////////////////
-
-
- /*We pass the 2 images (image & downscaledImage). Depending on the context we want to render in one or the other one:
- If (renderFullScaleThenDownscale and renderScaleOneUpstreamIfRenderScaleSupportDisabled)
- the image that is held by the cache will be 'image' and it will then be downscaled if needed.
- However if the render scale is not supported but input images are not rendered at full-scale ,
- we don't want to cache the full-scale image because it will be low res. Instead in that case we cache the downscaled image
- */
- bool useImageAsOutput;
RectI roi,upscaledRoi;
- if (renderFullScaleThenDownscale && renderScaleOneUpstreamIfRenderScaleSupportDisabled) {
+ if (renderFullScaleThenDownscale) {
//We cache 'image', hence the RoI should be expressed in its coordinates
//renderRoIInternal should check the bitmap of 'image' and not downscaledImage!
RectD canonicalRoI;
args.roi.toCanonical(args.mipMapLevel, par, rod, &canonicalRoI);
canonicalRoI.toPixelEnclosing(0, par, &roi);
upscaledRoi = roi;
- useImageAsOutput = true;
} else {
- //In that case the plug-in either supports render scale or doesn't support render scale but uses downscaled inputs
- //renderRoIInternal should check the bitmap of downscaledImage and not 'image'!
roi = args.roi;
- if (!renderFullScaleThenDownscale) {
- upscaledRoi = roi;
- } else {
- RectD canonicalRoI;
- args.roi.toCanonical(args.mipMapLevel, par, rod, &canonicalRoI);
- canonicalRoI.toPixelEnclosing(0, par, &upscaledRoi);
- }
- useImageAsOutput = false;
+ upscaledRoi = roi;
}
@@ -464,7 +445,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
}
}
- if ( (supportsRS == eSupportsMaybe) && (renderMappedMipMapLevel != 0) ) {
+ if ( (supportsRS == eSupportsMaybe) && (mipMapLevel != 0) ) {
// supportsRenderScaleMaybe may have changed, update it
supportsRS = supportsRenderScaleMaybe();
renderFullScaleThenDownscale = true;
@@ -594,7 +575,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
///Make sure the RoI falls within the image bounds
///Intersection will be in pixel coordinates
if (frameRenderArgs.tilesSupported) {
- if (useImageAsOutput) {
+ if (renderFullScaleThenDownscale) {
if ( !roi.intersect(upscaledImageBoundsNc, &roi) ) {
return eRenderRoIRetCodeOk;
}
@@ -613,24 +594,40 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
downscaledImageBoundsNc.intersect(args.roi, &downscaledImageBoundsNc);
#endif
} else {
- roi = useImageAsOutput ? upscaledImageBoundsNc : downscaledImageBoundsNc;
+ roi = renderFullScaleThenDownscale ? upscaledImageBoundsNc : downscaledImageBoundsNc;
}
const RectI & downscaledImageBounds = downscaledImageBoundsNc;
const RectI & upscaledImageBounds = upscaledImageBoundsNc;
RectD canonicalRoI;
- if (useImageAsOutput) {
+ if (renderFullScaleThenDownscale) {
roi.toCanonical(0, par, rod, &canonicalRoI);
} else {
roi.toCanonical(args.mipMapLevel, par, rod, &canonicalRoI);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// End Compute RoI /////////////////////////////////////////////////////////////////////////
-
+ bool draftModeSupported = supportsRenderQuality();
bool isFrameVaryingOrAnimated = isFrameVaryingOrAnimated_Recursive();
bool createInCache = shouldCacheOutput(isFrameVaryingOrAnimated);
- Natron::ImageKey key = Natron::Image::makeKey(getNode().get(),nodeHash, isFrameVaryingOrAnimated, args.time, args.view, frameRenderArgs.draftMode);
+ Natron::ImageKey key(getNode().get(),
+ nodeHash,
+ isFrameVaryingOrAnimated,
+ args.time,
+ args.view,
+ 1.,
+ draftModeSupported && frameRenderArgs.draftMode,
+ renderMappedMipMapLevel == 0 && args.mipMapLevel != 0 && !renderScaleOneUpstreamIfRenderScaleSupportDisabled);
+ Natron::ImageKey nonDraftKey(getNode().get(),
+ nodeHash,
+ isFrameVaryingOrAnimated,
+ args.time,
+ args.view,
+ 1.,
+ false,
+ renderMappedMipMapLevel == 0 && args.mipMapLevel != 0 && !renderScaleOneUpstreamIfRenderScaleSupportDisabled);
+
bool useDiskCacheNode = dynamic_cast(this) != NULL;
@@ -675,17 +672,25 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
}
}
assert(components);
- getImageFromCacheAndConvertIfNeeded(createInCache, useDiskCacheNode, key, renderMappedMipMapLevel,
- useImageAsOutput ? &upscaledImageBounds : &downscaledImageBounds,
- &rod,
- args.bitdepth, *it,
- outputDepth,
- *components,
- args.inputImagesList,
- frameRenderArgs.stats,
- &plane.fullscaleImage);
-
-
+
+ int nLookups = draftModeSupported && frameRenderArgs.draftMode ? 2 : 1;
+
+ for (int n = 0; n < nLookups; ++n) {
+ getImageFromCacheAndConvertIfNeeded(createInCache, useDiskCacheNode, n == 0 ? nonDraftKey : key, renderMappedMipMapLevel,
+ renderFullScaleThenDownscale ? &upscaledImageBounds : &downscaledImageBounds,
+ &rod,
+ args.bitdepth, *it,
+ outputDepth,
+ *components,
+ args.inputImagesList,
+ frameRenderArgs.stats,
+ &plane.fullscaleImage);
+ if (plane.fullscaleImage) {
+ break;
+ }
+ }
+
+
if (byPassCache) {
if (plane.fullscaleImage) {
appPTR->removeFromNodeCache( key.getHash() );
@@ -891,13 +896,13 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
if (!frameRenderArgs.tilesSupported && !rectsLeftToRender.empty() && isPlaneCached) {
///if the effect doesn't support tiles, just render the whole rod again even though
rectsLeftToRender.clear();
- rectsLeftToRender.push_back(useImageAsOutput ? upscaledImageBounds : downscaledImageBounds);
+ rectsLeftToRender.push_back(renderFullScaleThenDownscale ? upscaledImageBounds : downscaledImageBounds);
}
} else {
if (frameRenderArgs.tilesSupported) {
rectsLeftToRender.push_back(roi);
} else {
- rectsLeftToRender.push_back(useImageAsOutput ? upscaledImageBounds : downscaledImageBounds);
+ rectsLeftToRender.push_back(renderFullScaleThenDownscale ? upscaledImageBounds : downscaledImageBounds);
}
}
@@ -998,7 +1003,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
}
RectD canonicalRoI;
- if (useImageAsOutput) {
+ if (renderFullScaleThenDownscale) {
it->rect.toCanonical(0, par, rod, &canonicalRoI);
} else {
it->rect.toCanonical(args.mipMapLevel, par, rod, &canonicalRoI);
@@ -1074,7 +1079,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
assert(components);
getImageFromCacheAndConvertIfNeeded(createInCache, useDiskCacheNode, key, renderMappedMipMapLevel,
- useImageAsOutput ? &upscaledImageBounds : &downscaledImageBounds,
+ renderFullScaleThenDownscale ? &upscaledImageBounds : &downscaledImageBounds,
&rod,
args.bitdepth, it->first,
outputDepth, *components,
@@ -1101,7 +1106,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
if (frameRenderArgs.tilesSupported) {
rectsLeftToRender.push_back(roi);
} else {
- rectsLeftToRender.push_back(useImageAsOutput ? upscaledImageBounds : downscaledImageBounds);
+ rectsLeftToRender.push_back(renderFullScaleThenDownscale ? upscaledImageBounds : downscaledImageBounds);
}
@@ -1125,7 +1130,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
}
RectD canonicalRoI;
- if (useImageAsOutput) {
+ if (renderFullScaleThenDownscale) {
it->rect.toCanonical(0, par, rod, &canonicalRoI);
} else {
it->rect.toCanonical(args.mipMapLevel, par, rod, &canonicalRoI);
@@ -1185,7 +1190,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
if (!it->second.fullscaleImage) {
///The image is not cached
- allocateImagePlane(key, rod, downscaledImageBounds, upscaledImageBounds, isProjectFormat, framesNeeded, *components, args.bitdepth, par, args.mipMapLevel, renderFullScaleThenDownscale, renderScaleOneUpstreamIfRenderScaleSupportDisabled, useDiskCacheNode, createInCache, &it->second.fullscaleImage, &it->second.downscaleImage);
+ allocateImagePlane(key, rod, downscaledImageBounds, upscaledImageBounds, isProjectFormat, framesNeeded, *components, args.bitdepth, par, args.mipMapLevel, renderFullScaleThenDownscale, useDiskCacheNode, createInCache, &it->second.fullscaleImage, &it->second.downscaleImage);
} else {
/*
* There might be a situation where the RoD of the cached image
@@ -1204,7 +1209,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
* Another thread might have allocated the same image in the cache but with another RoI, make sure
* it is big enough for us, or resize it to our needs.
*/
- bool hasResized = it->second.fullscaleImage->ensureBounds(useImageAsOutput ? upscaledImageBounds : downscaledImageBounds,
+ bool hasResized = it->second.fullscaleImage->ensureBounds(renderFullScaleThenDownscale ? upscaledImageBounds : downscaledImageBounds,
fillGrownBoundsWithZeroes, fillGrownBoundsWithZeroes);
@@ -1254,7 +1259,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
///Only use trimap system if the render cannot be aborted.
if (!frameRenderArgs.canAbort && frameRenderArgs.isRenderResponseToUserInteraction) {
for (std::map::iterator it = planesToRender.planes.begin(); it != planesToRender.planes.end(); ++it) {
- _imp->markImageAsBeingRendered(useImageAsOutput ? it->second.fullscaleImage : it->second.downscaleImage);
+ _imp->markImageAsBeingRendered(renderFullScaleThenDownscale ? it->second.fullscaleImage : it->second.downscaleImage);
}
}
#endif
@@ -1314,7 +1319,6 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
frameRenderArgs.isRenderResponseToUserInteraction,
nodeHash,
renderFullScaleThenDownscale,
- renderScaleOneUpstreamIfRenderScaleSupportDisabled,
byPassCache,
outputDepth,
outputClipPrefComps,
@@ -1332,17 +1336,17 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
for (std::map::iterator it = planesToRender.planes.begin(); it != planesToRender.planes.end(); ++it) {
if (!renderAborted) {
if ( (renderRetCode == eRenderRoIStatusRenderFailed) || !planesToRender.isBeingRenderedElsewhere ) {
- _imp->unmarkImageAsBeingRendered(useImageAsOutput ? it->second.fullscaleImage : it->second.downscaleImage,
+ _imp->unmarkImageAsBeingRendered(renderFullScaleThenDownscale ? it->second.fullscaleImage : it->second.downscaleImage,
renderRetCode == eRenderRoIStatusRenderFailed);
} else {
if ( !_imp->waitForImageBeingRenderedElsewhereAndUnmark(roi,
- useImageAsOutput ? it->second.fullscaleImage : it->second.downscaleImage) ) {
+ renderFullScaleThenDownscale ? it->second.fullscaleImage : it->second.downscaleImage) ) {
renderAborted = true;
}
}
} else {
- appPTR->removeFromNodeCache(useImageAsOutput ? it->second.fullscaleImage : it->second.downscaleImage);
- _imp->unmarkImageAsBeingRendered(useImageAsOutput ? it->second.fullscaleImage : it->second.downscaleImage, true);
+ appPTR->removeFromNodeCache(renderFullScaleThenDownscale ? it->second.fullscaleImage : it->second.downscaleImage);
+ _imp->unmarkImageAsBeingRendered(renderFullScaleThenDownscale ? it->second.fullscaleImage : it->second.downscaleImage, true);
return eRenderRoIRetCodeAborted;
}
@@ -1376,10 +1380,10 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
for (std::map::iterator it = planesToRender.planes.begin(); it != planesToRender.planes.end(); ++it) {
if (!frameRenderArgs.tilesSupported) {
//assert that bounds are consistent with the RoD if tiles are not supported
- const RectD & srcRodCanonical = useImageAsOutput ? it->second.fullscaleImage->getRoD() : it->second.downscaleImage->getRoD();
+ const RectD & srcRodCanonical = renderFullScaleThenDownscale ? it->second.fullscaleImage->getRoD() : it->second.downscaleImage->getRoD();
RectI srcBounds;
- srcRodCanonical.toPixelEnclosing(useImageAsOutput ? it->second.fullscaleImage->getMipMapLevel() : it->second.downscaleImage->getMipMapLevel(), par, &srcBounds);
- RectI srcRealBounds = useImageAsOutput ? it->second.fullscaleImage->getBounds() : it->second.downscaleImage->getBounds();
+ srcRodCanonical.toPixelEnclosing(renderFullScaleThenDownscale ? it->second.fullscaleImage->getMipMapLevel() : it->second.downscaleImage->getMipMapLevel(), par, &srcBounds);
+ RectI srcRealBounds = renderFullScaleThenDownscale ? it->second.fullscaleImage->getBounds() : it->second.downscaleImage->getBounds();
assert(srcRealBounds.x1 == srcBounds.x1);
assert(srcRealBounds.x2 == srcBounds.x2);
assert(srcRealBounds.y1 == srcBounds.y1);
@@ -1387,8 +1391,8 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
}
std::list restToRender;
- if (useImageAsOutput) {
- it->second.fullscaleImage->getRestToRender(roi, restToRender);
+ if (renderFullScaleThenDownscale) {
+ it->second.fullscaleImage->getRestToRender(upscaledRoi, restToRender);
} else {
it->second.downscaleImage->getRestToRender(roi, restToRender);
}
@@ -1478,7 +1482,6 @@ EffectInstance::renderRoIInternal(double time,
bool isRenderMadeInResponseToUserInteraction,
U64 nodeHash,
bool renderFullScaleThenDownscale,
- bool useScaleOneInputImages,
bool byPassCache,
Natron::ImageBitDepthEnum outputClipPrefDepth,
const std::list & outputClipPrefsComps,
@@ -1600,7 +1603,6 @@ EffectInstance::renderRoIInternal(double time,
tiledArgs.frameArgs = frameArgs;
tiledArgs.frameTLS = tlsCopy;
tiledArgs.renderFullScaleThenDownscale = renderFullScaleThenDownscale;
- tiledArgs.renderUseScaleOneInputs = useScaleOneInputImages;
tiledArgs.isRenderResponseToUserInteraction = isRenderMadeInResponseToUserInteraction;
tiledArgs.firstFrame = firstFrame;
tiledArgs.lastFrame = lastFrame;
@@ -1659,7 +1661,7 @@ EffectInstance::renderRoIInternal(double time,
}
} else {
for (std::list::const_iterator it = planesToRender.rectsToRender.begin(); it != planesToRender.rectsToRender.end(); ++it) {
- RenderingFunctorRetEnum functorRet = tiledRenderingFunctor(currentThread, frameArgs, *it, tlsCopy, renderFullScaleThenDownscale, useScaleOneInputImages, isSequentialRender, isRenderMadeInResponseToUserInteraction, firstFrame, lastFrame, preferredInput, mipMapLevel, renderMappedMipMapLevel, rod, time, view, par, byPassCache, outputClipPrefDepth, outputClipPrefsComps, compsNeeded, processChannels, planesToRender);
+ RenderingFunctorRetEnum functorRet = tiledRenderingFunctor(currentThread, frameArgs, *it, tlsCopy, renderFullScaleThenDownscale, isSequentialRender, isRenderMadeInResponseToUserInteraction, firstFrame, lastFrame, preferredInput, mipMapLevel, renderMappedMipMapLevel, rod, time, view, par, byPassCache, outputClipPrefDepth, outputClipPrefsComps, compsNeeded, processChannels, planesToRender);
if ( (functorRet == eRenderingFunctorRetFailed) || (functorRet == eRenderingFunctorRetAborted) ) {
renderStatus = functorRet;
diff --git a/Engine/Image.cpp b/Engine/Image.cpp
index 6953e08757..79fe6d747c 100644
--- a/Engine/Image.cpp
+++ b/Engine/Image.cpp
@@ -634,7 +634,7 @@ Image::Image(const ImageComponents& components,
, _useBitmap(useBitmap)
{
- setCacheEntry(makeKey(0,0,false,0,0, false),
+ setCacheEntry(makeKey(0, 0, false, 0, 0, false, false),
boost::shared_ptr( new ImageParams( mipMapLevel,
regionOfDefinition,
par,
@@ -695,9 +695,10 @@ Image::makeKey(const CacheEntryHolder* holder,
bool frameVaryingOrAnimated,
double time,
int view,
- bool draftMode)
+ bool draftMode,
+ bool fullScaleWithDownscaleInputs)
{
- return ImageKey(holder,nodeHashKey,frameVaryingOrAnimated,time,view, 1., draftMode);
+ return ImageKey(holder,nodeHashKey,frameVaryingOrAnimated,time,view, 1., draftMode, fullScaleWithDownscaleInputs);
}
boost::shared_ptr
diff --git a/Engine/Image.h b/Engine/Image.h
index 73bd83ba7f..e56222b8bc 100644
--- a/Engine/Image.h
+++ b/Engine/Image.h
@@ -203,7 +203,8 @@ namespace Natron {
bool frameVaryingOrAnimated,
double time,
int view,
- bool draftMode);
+ bool draftMode,
+ bool fullScaleWithDownscaleInputs);
static boost::shared_ptr makeParams(int cost,
const RectD & rod, // the image rod in canonical coordinates
const double par,
diff --git a/Engine/ImageKey.cpp b/Engine/ImageKey.cpp
index 507716859d..3d13528ca1 100644
--- a/Engine/ImageKey.cpp
+++ b/Engine/ImageKey.cpp
@@ -35,6 +35,7 @@ ImageKey::ImageKey()
, _view(0)
, _pixelAspect(1)
, _draftMode(false)
+, _fullScaleWithDownscaleInputs(false)
{
}
@@ -45,7 +46,8 @@ ImageKey::ImageKey(const CacheEntryHolder* holder,
//unsigned int mipMapLevel, //< Store different mipmapLevels under the same key
int view,
double pixelAspect,
- bool draftMode)
+ bool draftMode,
+ bool fullScaleWithDownscaleInputs)
: KeyHelper(holder)
, _nodeHashKey(nodeHashKey)
, _frameVaryingOrAnimated(frameVaryingOrAnimated)
@@ -53,6 +55,7 @@ ImageKey::ImageKey(const CacheEntryHolder* holder,
, _view(view)
, _pixelAspect(pixelAspect)
, _draftMode(draftMode)
+, _fullScaleWithDownscaleInputs(fullScaleWithDownscaleInputs)
{
}
@@ -66,6 +69,7 @@ ImageKey::fillHash(Hash64* hash) const
hash->append(_view);
hash->append(_pixelAspect);
hash->append(_draftMode);
+ hash->append(_fullScaleWithDownscaleInputs);
}
bool
@@ -76,12 +80,14 @@ ImageKey::operator==(const ImageKey & other) const
_time == other._time &&
_view == other._view &&
_pixelAspect == other._pixelAspect &&
- _draftMode == other._draftMode;
+ _draftMode == other._draftMode &&
+ _fullScaleWithDownscaleInputs == other._fullScaleWithDownscaleInputs;
} else {
return _nodeHashKey == other._nodeHashKey &&
_view == other._view &&
_pixelAspect == other._pixelAspect &&
- _draftMode == other._draftMode;
+ _draftMode == other._draftMode &&
+ _fullScaleWithDownscaleInputs == other._fullScaleWithDownscaleInputs;
}
}
diff --git a/Engine/ImageKey.h b/Engine/ImageKey.h
index 749e676f5e..61cb467d0d 100644
--- a/Engine/ImageKey.h
+++ b/Engine/ImageKey.h
@@ -39,6 +39,10 @@ class ImageKey
int _view;
double _pixelAspect;
bool _draftMode;
+
+ //When true that means the image has been computed based on inputs using a mipmaplevel != 0
+ //hence it is probably not very high quality, even though the mipmap level is 0
+ bool _fullScaleWithDownscaleInputs;
ImageKey();
@@ -48,7 +52,8 @@ class ImageKey
double time,
int view,
double pixelAspect,
- bool draftMode);
+ bool draftMode,
+ bool fullScaleWithDownscaleInputs);
void fillHash(Hash64* hash) const;
diff --git a/Engine/OfxEffectInstance.cpp b/Engine/OfxEffectInstance.cpp
index 5e0d42318a..d9847bf455 100644
--- a/Engine/OfxEffectInstance.cpp
+++ b/Engine/OfxEffectInstance.cpp
@@ -2714,6 +2714,12 @@ OfxEffectInstance::getMinorVersion() const
return effectInstance()->getPlugin()->getVersionMinor();
}
+bool
+OfxEffectInstance::supportsRenderQuality() const
+{
+ return effectInstance()->supportsRenderQuality();
+}
+
bool
OfxEffectInstance::supportsTiles() const
{
diff --git a/Engine/OfxEffectInstance.h b/Engine/OfxEffectInstance.h
index 34a35d61bf..ecb21477bc 100644
--- a/Engine/OfxEffectInstance.h
+++ b/Engine/OfxEffectInstance.h
@@ -231,6 +231,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
* full RoD images to the effect whenever it fetches one.
**/
virtual bool supportsTiles() const OVERRIDE FINAL WARN_UNUSED_RETURN;
+ virtual bool supportsRenderQuality() const OVERRIDE FINAL WARN_UNUSED_RETURN;
virtual Natron::PluginOpenGLRenderSupport supportsOpenGLRender() const OVERRIDE FINAL WARN_UNUSED_RETURN;
virtual bool doesTemporalClipAccess() const OVERRIDE FINAL WARN_UNUSED_RETURN;
diff --git a/Engine/RotoContext.cpp b/Engine/RotoContext.cpp
index 1824558d0c..55fff61594 100644
--- a/Engine/RotoContext.cpp
+++ b/Engine/RotoContext.cpp
@@ -2353,7 +2353,7 @@ RotoContext::renderMaskFromStroke(const boost::shared_ptr& str
hash.append(stroke->getMergeNode()->getLiveInstance()->getRenderHash());
hash.computeHash();
- Natron::ImageKey key = Natron::Image::makeKey(stroke.get(),hash.value(), true ,time, view, false);
+ Natron::ImageKey key = Natron::Image::makeKey(stroke.get(),hash.value(), true ,time, view, false, false);
{
QMutexLocker k(&_imp->cacheAccessMutex);
diff --git a/libs/OpenFX b/libs/OpenFX
index de8216d05b..6945782584 160000
--- a/libs/OpenFX
+++ b/libs/OpenFX
@@ -1 +1 @@
-Subproject commit de8216d05b0d4f230734d1b7a2b7b7144a4f9f15
+Subproject commit 6945782584e9806a655f32b9459280d53c06e143
From 3969ae6c1383e6efeac2da27e41c8d1fb2cd297d Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Sun, 27 Sep 2015 20:51:33 +0200
Subject: [PATCH 004/178] Remove upscaledRoi
---
Engine/EffectInstanceRenderRoI.cpp | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/Engine/EffectInstanceRenderRoI.cpp b/Engine/EffectInstanceRenderRoI.cpp
index 4d3f41341d..b3c061e9b0 100644
--- a/Engine/EffectInstanceRenderRoI.cpp
+++ b/Engine/EffectInstanceRenderRoI.cpp
@@ -291,7 +291,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// End get RoD ///////////////////////////////////////////////////////////////
- RectI roi,upscaledRoi;
+ RectI roi;
if (renderFullScaleThenDownscale) {
//We cache 'image', hence the RoI should be expressed in its coordinates
@@ -299,10 +299,8 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
RectD canonicalRoI;
args.roi.toCanonical(args.mipMapLevel, par, rod, &canonicalRoI);
canonicalRoI.toPixelEnclosing(0, par, &roi);
- upscaledRoi = roi;
} else {
roi = args.roi;
- upscaledRoi = roi;
}
@@ -590,7 +588,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
}
#ifndef NATRON_ALWAYS_ALLOCATE_FULL_IMAGE_BOUNDS
///just allocate the roi
- upscaledImageBoundsNc.intersect(upscaledRoi, &upscaledImageBoundsNc);
+ upscaledImageBoundsNc.intersect(roi, &upscaledImageBoundsNc);
downscaledImageBoundsNc.intersect(args.roi, &downscaledImageBoundsNc);
#endif
} else {
@@ -823,7 +821,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
#if NATRON_ENABLE_TRIMAP
if (!frameRenderArgs.canAbort && frameRenderArgs.isRenderResponseToUserInteraction) {
#ifndef DEBUG
- isPlaneCached->getRestToRender_trimap(upscaledRoi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
+ isPlaneCached->getRestToRender_trimap(roi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
#else
// in debug mode, check that the result of getRestToRender_trimap and getRestToRender is the same if the image
// is not currently rendered concurrently
@@ -837,9 +835,9 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
}
if (!ibr) {
Image::ReadAccess racc( isPlaneCached.get() );
- isPlaneCached->getRestToRender_trimap(upscaledRoi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
+ isPlaneCached->getRestToRender_trimap(roi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
std::list tmpRects;
- isPlaneCached->getRestToRender(upscaledRoi, tmpRects);
+ isPlaneCached->getRestToRender(roi, tmpRects);
//If it crashes here that means the image is no longer being rendered but its bitmap still contains PIXEL_UNAVAILABLE pixels.
//The other thread should have removed that image from the cache or marked the image as rendered.
@@ -851,14 +849,14 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
assert(*it == *oIt);
}
} else {
- isPlaneCached->getRestToRender_trimap(upscaledRoi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
+ isPlaneCached->getRestToRender_trimap(roi, rectsLeftToRender, &planesToRender.isBeingRenderedElsewhere);
}
#endif
} else {
- isPlaneCached->getRestToRender(upscaledRoi, rectsLeftToRender);
+ isPlaneCached->getRestToRender(roi, rectsLeftToRender);
}
#else
- isPlaneCached->getRestToRender(upscaledRoi, rectsLeftToRender);
+ isPlaneCached->getRestToRender(roi, rectsLeftToRender);
#endif
if ( isDuringPaintStroke && !rectsLeftToRender.empty() && !lastStrokePixelRoD.isNull() ) {
rectsLeftToRender.clear();
@@ -1392,7 +1390,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
std::list restToRender;
if (renderFullScaleThenDownscale) {
- it->second.fullscaleImage->getRestToRender(upscaledRoi, restToRender);
+ it->second.fullscaleImage->getRestToRender(roi, restToRender);
} else {
it->second.downscaleImage->getRestToRender(roi, restToRender);
}
@@ -1423,7 +1421,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
false) );
}
- it->second.fullscaleImage->downscaleMipMap( it->second.fullscaleImage->getRoD(), upscaledRoi, 0, args.mipMapLevel, false, it->second.downscaleImage.get() );
+ it->second.fullscaleImage->downscaleMipMap( it->second.fullscaleImage->getRoD(), roi, 0, args.mipMapLevel, false, it->second.downscaleImage.get() );
}
///The image might need to be converted to fit the original requested format
bool imageConversionNeeded = it->first != it->second.downscaleImage->getComponents() || args.bitdepth != it->second.downscaleImage->getBitDepth();
From 7454656de1bae26def8ca447568dbcfe8ed1b4b5 Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Sun, 27 Sep 2015 21:06:34 +0200
Subject: [PATCH 005/178] Fix renderFullScale
---
Engine/EffectInstance.cpp | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/Engine/EffectInstance.cpp b/Engine/EffectInstance.cpp
index f654a41f90..73dfb69eeb 100644
--- a/Engine/EffectInstance.cpp
+++ b/Engine/EffectInstance.cpp
@@ -2258,32 +2258,34 @@ EffectInstance::renderHandler(RenderArgs & args,
assert(it->second.fullscaleImage != it->second.downscaleImage && it->second.renderMappedImage == it->second.fullscaleImage);
-
- if ( ( it->second.downscaleImage->getComponents() != it->second.tmpImage->getComponents() ) ||
- ( it->second.downscaleImage->getBitDepth() != it->second.tmpImage->getBitDepth() ) ) {
+ it->second.tmpImage->copyUnProcessedChannels(renderMappedRectToRender, planes.outputPremult, originalImagePremultiplication, processChannels, originalInputImage);
+ if (useMaskMix) {
+ it->second.tmpImage->applyMaskMix(renderMappedRectToRender, maskImage.get(), originalInputImage.get(), doMask, false, mix);
+ }
+ if ( ( it->second.fullscaleImage->getComponents() != it->second.tmpImage->getComponents() ) ||
+ ( it->second.fullscaleImage->getBitDepth() != it->second.tmpImage->getBitDepth() ) ) {
/*
* BitDepth/Components conversion required as well as downscaling, do conversion to a tmp buffer
*/
- ImagePtr tmp( new Image(it->second.downscaleImage->getComponents(), it->second.tmpImage->getRoD(), it->second.tmpImage->getBounds(), mipMapLevel, it->second.tmpImage->getPixelAspectRatio(), it->second.downscaleImage->getBitDepth(), false) );
+ ImagePtr tmp( new Image(it->second.fullscaleImage->getComponents(), it->second.tmpImage->getRoD(), it->second.tmpImage->getBounds(), mipMapLevel, it->second.tmpImage->getPixelAspectRatio(), it->second.fullscaleImage->getBitDepth(), false) );
it->second.tmpImage->convertToFormat( it->second.tmpImage->getBounds(),
getApp()->getDefaultColorSpaceForBitDepth( it->second.tmpImage->getBitDepth() ),
- getApp()->getDefaultColorSpaceForBitDepth( it->second.downscaleImage->getBitDepth() ),
+ getApp()->getDefaultColorSpaceForBitDepth( it->second.fullscaleImage->getBitDepth() ),
-1, false, unPremultRequired, tmp.get() );
tmp->downscaleMipMap( it->second.tmpImage->getRoD(),
actionArgs.roi, 0, mipMapLevel, false, it->second.downscaleImage.get() );
+ it->second.fullscaleImage->pasteFrom(*tmp, it->second.fullscaleImage->getBounds(), false);
} else {
/*
* Downscaling required only
*/
it->second.tmpImage->downscaleMipMap( it->second.tmpImage->getRoD(),
actionArgs.roi, 0, mipMapLevel, false, it->second.downscaleImage.get() );
+ it->second.fullscaleImage->pasteFrom(*(it->second.tmpImage), it->second.fullscaleImage->getBounds(), false);
}
- it->second.downscaleImage->copyUnProcessedChannels(downscaledRectToRender, planes.outputPremult, originalImagePremultiplication, processChannels, originalInputImage);
- if (useMaskMix) {
- it->second.downscaleImage->applyMaskMix(downscaledRectToRender, maskImage.get(), originalInputImage.get(), doMask, false, mix);
- }
+
it->second.fullscaleImage->markForRendered(renderMappedRectToRender);
} else { // if (renderFullScaleThenDownscale) {
From f62a727e6aeb385ef35920c61b96913afea5f468 Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Sun, 27 Sep 2015 22:38:35 +0200
Subject: [PATCH 006/178] Fix unit test
---
Tests/Image_Test.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Tests/Image_Test.cpp b/Tests/Image_Test.cpp
index 780286536d..93a7483097 100644
--- a/Tests/Image_Test.cpp
+++ b/Tests/Image_Test.cpp
@@ -113,7 +113,7 @@ TEST(ImageKeyTest,Equality) {
SequenceTime time1 = 0;
int view1 = 0;
double pa1 = 1.;
- Natron::ImageKey key1(0,randomHashKey1, false, time1,view1,pa1, false);
+ Natron::ImageKey key1(0,randomHashKey1, false, time1,view1,pa1, false, false);
U64 keyHash1 = key1.getHash();
@@ -122,7 +122,7 @@ TEST(ImageKeyTest,Equality) {
SequenceTime time2 = time1;
int view2 = view1;
double pa2 = pa1;
- Natron::ImageKey key2(0,randomHashKey2, false, time2,view2,pa2, false);
+ Natron::ImageKey key2(0,randomHashKey2, false, time2,view2,pa2, false, false);
U64 keyHash2 = key2.getHash();
ASSERT_TRUE(keyHash1 == keyHash2);
}
@@ -134,7 +134,7 @@ TEST(ImageKeyTest,Difference) {
SequenceTime time1 = 0;
int view1 = 0;
double pa1 = 1.;
- Natron::ImageKey key1(0,randomHashKey1,false, time1,view1,pa1, false);
+ Natron::ImageKey key1(0,randomHashKey1,false, time1,view1,pa1, false, false);
U64 keyHash1 = key1.getHash();
@@ -144,7 +144,7 @@ TEST(ImageKeyTest,Difference) {
SequenceTime time2 = time1;
int view2 = view1;
double pa2 = pa1;
- Natron::ImageKey key2(0,randomHashKey2,false, time2,view2,pa2, false);
+ Natron::ImageKey key2(0,randomHashKey2,false, time2,view2,pa2, false, false);
U64 keyHash2 = key2.getHash();
ASSERT_TRUE(keyHash1 != keyHash2);
}
From 903213f5d8c41e1694a38f26fa612e6d9a771564 Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Sun, 27 Sep 2015 23:35:42 +0200
Subject: [PATCH 007/178] update openfx
---
libs/OpenFX | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libs/OpenFX b/libs/OpenFX
index 6945782584..2b409121b4 160000
--- a/libs/OpenFX
+++ b/libs/OpenFX
@@ -1 +1 @@
-Subproject commit 6945782584e9806a655f32b9459280d53c06e143
+Subproject commit 2b409121b4ef8e89c92e19dd8a77400c6d4cfd8f
From d486d851efeeaf933521d004e31dbdaffa186932 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?=
Date: Mon, 28 Sep 2015 03:34:35 +0200
Subject: [PATCH 008/178] Linux SDK: build librsvg+pango (and depends, total 14
new)
---
tools/linux/common.sh | 16 +-
tools/linux/include/scripts/build-sdk.sh | 287 ++++++++++++++++---
tools/linux/include/scripts/setup-centos6.sh | 2 +-
3 files changed, 258 insertions(+), 47 deletions(-)
diff --git a/tools/linux/common.sh b/tools/linux/common.sh
index d65c35e572..dee0ccdfb3 100644
--- a/tools/linux/common.sh
+++ b/tools/linux/common.sh
@@ -136,8 +136,8 @@ OCIO_TAR=OpenColorIO-1.0.9.tar.gz
OIIO_TAR=oiio-Release-1.5.18.tar.gz
PYSIDE_TAR=pyside-qt4.8+1.2.2.tar.bz2
SHIBOK_TAR=shiboken-1.2.2.tar.bz2
-#LIBXML_TAR=libxml2-2.9.2.tar.gz (#25)
-#LIBXSL_TAR=libxslt-1.1.28.tar.gz (#25)
+LIBXML_TAR=libxml2-2.9.2.tar.gz
+LIBXSLT_TAR=libxslt-1.1.28.tar.gz
SEE_TAR=SeExpr-rel-1.0.1.tar.gz
LIBRAW_TAR=LibRaw-0.16.0.tar.gz
PIX_TAR=pixman-0.32.6.tar.gz
@@ -158,6 +158,18 @@ DIRAC_TAR=schroedinger-1.0.11.tar.gz
ORC_TAR=orc-0.4.23.tar.xz
X264_TAR=x264-snapshot-20150725-2245.tar.bz2 #GPL-only
XVID_TAR=xvidcore-1.3.4.tar.gz #GPL-only
+ICU_TAR=icu4c-55_1-src.tgz
+ZLIB_TAR=zlib-1.2.8.tar.gz
+EXPAT_TAR=expat-2.1.0.tar.gz
+FCONFIG_TAR=fontconfig-2.10.2.tar.gz
+FTYPE_TAR=freetype-2.4.11.tar.gz
+FFI_TAR=libffi-3.2.1.tar.gz
+GLIB_TAR=glib-2.42.2.tar.xz
+BUZZ_TAR=harfbuzz-0.9.40.tar.bz2
+PANGO_TAR=pango-1.37.0.tar.xz
+BZIP_TAR=bzip2-1.0.6.tar.gz
+CROCO_TAR=libcroco-0.6.8.tar.xz
+SVG_TAR=librsvg-2.40.10.tar.xz
TC_GCC=4.8.5
TC_MPC=1.0.1
diff --git a/tools/linux/include/scripts/build-sdk.sh b/tools/linux/include/scripts/build-sdk.sh
index f5d7e7ace2..9cec28b81d 100644
--- a/tools/linux/include/scripts/build-sdk.sh
+++ b/tools/linux/include/scripts/build-sdk.sh
@@ -148,6 +148,37 @@ else
fi
export LD_LIBRARY_PATH
+# Install zlib
+if [ ! -f "$INSTALL_PATH/lib/libz.so.1" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$ZLIB_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$ZLIB_TAR" -O "$SRC_PATH/$ZLIB_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$ZLIB_TAR" || exit 1
+ cd zlib* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --enable-static --enable-shared || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
+# Install bzip
+if [ ! -f "$INSTALL_PATH/lib/libbz2.so" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$BZIP_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$BZIP_TAR" -O "$SRC_PATH/$BZIP_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$BZIP_TAR" || exit 1
+ cd bzip* || exit 1
+ sed -e 's/^CFLAGS=\(.*\)$/CFLAGS=\1 \$(BIGFILES)/' -i ./Makefile-libbz2_so || exit 1
+ make -f Makefile-libbz2_so || exit 1
+ install -m755 libbz2.so.1.0.6 $INSTALL_PATH/lib || exit 1
+ install -m644 bzlib.h $INSTALL_PATH/include/ || exit 1
+ cd $INSTALL_PATH/lib || exit 1
+ ln -s libbz2.so.1.0.6 libbz2.so || exit 1
+ ln -s libbz2.so.1.0.6 libbz2.so.1 || exit 1
+ ln -s libbz2.so.1.0.6 libbz2.so.1.0 || exit 1
+fi
+
# Install yasm
if [ ! -f "$INSTALL_PATH/bin/yasm" ]; then
cd "$TMP_PATH" || exit 1
@@ -174,6 +205,19 @@ if [ ! -f "$INSTALL_PATH/bin/cmake" ]; then
make install || exit 1
fi
+# Install icu
+if [ ! -f "$INSTALL_PATH/bin/icu-config" ]; then
+ cd $TMP_PATH || exit 1
+ if [ ! -f "$SRC_PATH/$ICU_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$ICU_TAR" -O "$SRC_PATH/$ICU_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$ICU_TAR" || exit 1
+ cd icu/source || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --enable-static --enable-shared || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
# Install Python2
if [ ! -f "$INSTALL_PATH/lib/pkgconfig/python2.pc" ]; then
cd "$TMP_PATH" || exit 1
@@ -217,6 +261,112 @@ PYTHON_PATH="$INSTALL_PATH/lib/python2.7"
PYTHON_INCLUDE="$INSTALL_PATH/include/python2.7"
export PKG_CONFIG_PATH LD_LIBRARY_PATH PATH QTDIR BOOST_ROOT OPENJPEG_HOME THIRD_PARTY_TOOLS_HOME PYTHON_HOME PYTHON_PATH PYTHON_INCLUDE
+# Install expat
+if [ ! -f "$INSTALL_PATH/lib/libexpat.so" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$EXPAT_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$EXPAT_TAR" -O "$SRC_PATH/$EXPAT_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$EXPAT_TAR" || exit 1
+ cd expat* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --enable-static --enable-shared || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
+# Install png
+if [ ! -f $INSTALL_PATH/lib/pkgconfig/libpng.pc ]; then
+ cd $TMP_PATH || exit 1
+ if [ ! -f $SRC_PATH/$PNG_TAR ]; then
+ wget $THIRD_PARTY_SRC_URL/$PNG_TAR -O $SRC_PATH/$PNG_TAR || exit 1
+ fi
+ tar xvf $SRC_PATH/$PNG_TAR || exit 1
+ cd libpng* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" CPPFLAGS="-I${INSTALL_PATH}/include" LDFLAGS="-L${INSTALL_PATH}/lib" ./configure --prefix=$INSTALL_PATH --libdir=$INSTALL_PATH/lib --enable-shared --enable-static || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+ mkdir -p $INSTALL_PATH/docs/png || exit 1
+ cp LIC* COP* README AUTH* CONT* $INSTALL_PATH/docs/png/
+fi
+
+# Install freetype
+if [ ! -f "$INSTALL_PATH/lib/libfreetype.so" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$FTYPE_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$FTYPE_TAR" -O "$SRC_PATH/$FTYPE_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$FTYPE_TAR" || exit 1
+ cd freetype* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --enable-static --enable-shared || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
+# Install fontconfig
+if [ ! -f "$INSTALL_PATH/lib/libfontconfig.so" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$FCONFIG_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$FCONFIG_TAR" -O "$SRC_PATH/$FCONFIG_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$FCONFIG_TAR" || exit 1
+ cd fontconfig* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --disable-docs --enable-static --enable-shared || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
+# Install ffi
+if [ ! -f "$INSTALL_PATH/lib/pkgconfig/libffi.pc" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$FFI_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$FFI_TAR" -O "$SRC_PATH/$FFI_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$FFI_TAR" || exit 1
+ cd libffi* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --disable-docs --enable-static --enable-shared || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
+# Install glib
+if [ ! -f "$INSTALL_PATH/lib/pkgconfig/glib-2.0.pc" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$GLIB_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$GLIB_TAR" -O "$SRC_PATH/$GLIB_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$GLIB_TAR" || exit 1
+ cd glib-2* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --disable-docs --enable-static --enable-shared || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
+# Install xml
+if [ ! -f "$INSTALL_PATH/lib/pkgconfig/libxml-2.0.pc" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$LIBXML_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$LIBXML_TAR" -O "$SRC_PATH/$LIBXML_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$LIBXML_TAR" || exit 1
+ cd libxml* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --disable-docs --enable-static --enable-shared --without-python || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
+# Install xslt
+if [ ! -f "$INSTALL_PATH/lib/libxslt.so.1" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$LIBXSLT_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$LIBXSLT_TAR" -O "$SRC_PATH/$LIBXSLT_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$LIBXSLT_TAR" || exit 1
+ cd libxslt* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --disable-docs --enable-static --enable-shared --without-python || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
# Install boost
if [ ! -f "$INSTALL_PATH/lib/libboost_atomic.so" ]; then
cd "$TMP_PATH" || exit 1
@@ -247,21 +397,6 @@ if [ ! -f $INSTALL_PATH/lib/libjpeg.a ]; then
cp LIC* COP* READ* AUTH* CONT* $INSTALL_PATH/docs/jpeg/
fi
-# Install png
-if [ ! -f $INSTALL_PATH/lib/pkgconfig/libpng.pc ]; then
- cd $TMP_PATH || exit 1
- if [ ! -f $SRC_PATH/$PNG_TAR ]; then
- wget $THIRD_PARTY_SRC_URL/$PNG_TAR -O $SRC_PATH/$PNG_TAR || exit 1
- fi
- tar xvf $SRC_PATH/$PNG_TAR || exit 1
- cd libpng* || exit 1
- env CFLAGS="$BF" CXXFLAGS="$BF" CPPFLAGS="-I${INSTALL_PATH}/include" LDFLAGS="-L${INSTALL_PATH}/lib" ./configure --prefix=$INSTALL_PATH --libdir=$INSTALL_PATH/lib --enable-shared --enable-static || exit 1
- make -j${MKJOBS} || exit 1
- make install || exit 1
- mkdir -p $INSTALL_PATH/docs/png || exit 1
- cp LIC* COP* README AUTH* CONT* $INSTALL_PATH/docs/png/
-fi
-
# Install tiff
if [ ! -f $INSTALL_PATH/lib/pkgconfig/libtiff-4.pc ]; then
cd $TMP_PATH || exit 1
@@ -365,6 +500,99 @@ if [ ! -f $INSTALL_PATH/lib/pkgconfig/OpenEXR.pc ]; then
cp LIC* COP* README AUTH* CONT* $INSTALL_PATH/docs/openexr/
fi
+# Install pixman
+if [ ! -f $INSTALL_PATH/lib/pkgconfig/pixman-1.pc ]; then
+ if [ ! -f $SRC_PATH/$PIX_TAR ]; then
+ wget $THIRD_PARTY_SRC_URL/$PIX_TAR -O $SRC_PATH/$PIX_TAR || exit 1
+ fi
+ tar xvf $SRC_PATH/$PIX_TAR || exit 1
+ cd pixman-* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" CPPFLAGS="-I${INSTALL_PATH}/include" LDFLAGS="-L${INSTALL_PATH}/lib" ./configure --prefix=$INSTALL_PATH --libdir=$INSTALL_PATH/lib --disable-shared --enable-static || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+ mkdir -p $INSTALL_PATH/docs/pixman || exit 1
+ cp COPYING* README AUTHORS $INSTALL_PATH/docs/pixman/ || exit 1
+fi
+
+# Install cairo
+if [ ! -f $INSTALL_PATH/lib/pkgconfig/cairo.pc ]; then
+ cd $TMP_PATH || exit 1
+ if [ ! -f $SRC_PATH/$CAIRO_TAR ]; then
+ wget $THIRD_PARTY_SRC_URL/$CAIRO_TAR -O $SRC_PATH/$CAIRO_TAR || exit 1
+ fi
+ tar xvf $SRC_PATH/$CAIRO_TAR || exit 1
+ cd cairo-* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" CPPFLAGS="-I${INSTALL_PATH}/include -I${INSTALL_PATH}/include/pixman-1" LDFLAGS="-L${INSTALL_PATH}/lib -lpixman-1" ./configure --prefix=$INSTALL_PATH --libdir=$INSTALL_PATH/lib --enable-shared --enable-static || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+ mkdir -p $INSTALL_PATH/docs/cairo || exit 1
+ cp COPYING* README AUTHORS $INSTALL_PATH/docs/cairo/ || exit 1
+fi
+
+# Install harbuzz
+if [ ! -f $INSTALL_PATH/lib/pkgconfig/harfbuzz.pc ]; then
+ cd $TMP_PATH || exit 1
+ if [ ! -f $SRC_PATH/$BUZZ_TAR ]; then
+ wget $THIRD_PARTY_SRC_URL/$BUZZ_TAR -O $SRC_PATH/$BUZZ_TAR || exit 1
+ fi
+ tar xvf $SRC_PATH/$BUZZ_TAR || exit 1
+ cd harfbuzz-* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" CPPFLAGS="-I${INSTALL_PATH}/include" LDFLAGS="-L${INSTALL_PATH}/lib" ./configure --prefix=$INSTALL_PATH --libdir=$INSTALL_PATH/lib --disable-docs --enable-static --enable-shared --with-freetype --with-cairo --with-gobject --with-glib --with-icu || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+ mkdir -p $INSTALL_PATH/docs/cairo || exit 1
+ cp COPYING* README AUTHORS $INSTALL_PATH/docs/cairo/ || exit 1
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$FTYPE_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$FTYPE_TAR" -O "$SRC_PATH/$FTYPE_TAR" || exit 1
+ fi
+ rm -rf freetype*
+ tar xvf "$SRC_PATH/$FTYPE_TAR" || exit 1
+ cd freetype* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --enable-static --enable-shared || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
+# Install pango
+if [ ! -f "$INSTALL_PATH/lib/pkgconfig/pango.pc" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$PANGO_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$PANGO_TAR" -O "$SRC_PATH/$PANGO_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$PANGO_TAR" || exit 1
+ cd pango-* || exit 1
+ env FONTCONFIG_CFLAGS="-I$INSTALL_PATH/include" FONTCONFIG_LIBS="-L$INSTALL_PATH/lib -lfontconfig" CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --disable-docs --enable-static --enable-shared --with-included-modules=basic-fc || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
+# Install croco
+if [ ! -f "$INSTALL_PATH/lib/libcroco-0.6.so.3" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$CROCO_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$CROCO_TAR" -O "$SRC_PATH/$CROCO_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$CROCO_TAR" || exit 1
+ cd libcroco-* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --disable-docs --enable-static --enable-shared || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
+# Install svg
+if [ ! -f "$INSTALL_PATH/lib/pkgconfig/librsvg-2.0.pc" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$SVG_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$SVG_TAR" -O "$SRC_PATH/$SVG_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$SVG_TAR" || exit 1
+ cd librsvg-* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --disable-docs --enable-static --enable-shared --disable-introspection --disable-vala --disable-pixbuf-loader || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
# Install magick
if [ "$REBUILD_MAGICK" = "1" ]; then
rm -rf $INSTALL_PATH/include/ImageMagick-6/ $INSTALL_PATH/lib/libMagick* $INSTALL_PATH/share/ImageMagick-6/ $INSTALL_PATH/lib/pkgconfig/{Image,Magick}*
@@ -401,35 +629,6 @@ if [ ! -f $INSTALL_PATH/lib/pkgconfig/glew.pc ]; then
cp LICENSE.txt README.txt $INSTALL_PATH/docs/glew/ || exit 1
fi
-# Install pixman
-if [ ! -f $INSTALL_PATH/lib/pkgconfig/pixman-1.pc ]; then
- if [ ! -f $SRC_PATH/$PIX_TAR ]; then
- wget $THIRD_PARTY_SRC_URL/$PIX_TAR -O $SRC_PATH/$PIX_TAR || exit 1
- fi
- tar xvf $SRC_PATH/$PIX_TAR || exit 1
- cd pixman-* || exit 1
- env CFLAGS="$BF" CXXFLAGS="$BF" CPPFLAGS="-I${INSTALL_PATH}/include" LDFLAGS="-L${INSTALL_PATH}/lib" ./configure --prefix=$INSTALL_PATH --libdir=$INSTALL_PATH/lib --disable-shared --enable-static || exit 1
- make -j${MKJOBS} || exit 1
- make install || exit 1
- mkdir -p $INSTALL_PATH/docs/pixman || exit 1
- cp COPYING* README AUTHORS $INSTALL_PATH/docs/pixman/ || exit 1
-fi
-
-# Install cairo
-if [ ! -f $INSTALL_PATH/lib/pkgconfig/cairo.pc ]; then
- cd $TMP_PATH || exit 1
- if [ ! -f $SRC_PATH/$CAIRO_TAR ]; then
- wget $THIRD_PARTY_SRC_URL/$CAIRO_TAR -O $SRC_PATH/$CAIRO_TAR || exit 1
- fi
- tar xvf $SRC_PATH/$CAIRO_TAR || exit 1
- cd cairo-* || exit 1
- env CFLAGS="$BF" CXXFLAGS="$BF" CPPFLAGS="-I${INSTALL_PATH}/include -I${INSTALL_PATH}/include/pixman-1" LDFLAGS="-L${INSTALL_PATH}/lib -lpixman-1" ./configure --prefix=$INSTALL_PATH --libdir=$INSTALL_PATH/lib --enable-shared --enable-static || exit 1
- make -j${MKJOBS} || exit 1
- make install || exit 1
- mkdir -p $INSTALL_PATH/docs/cairo || exit 1
- cp COPYING* README AUTHORS $INSTALL_PATH/docs/cairo/ || exit 1
-fi
-
# Install ocio
if [ ! -f $INSTALL_PATH/lib/libOpenColorIO.so ]; then
cd $TMP_PATH || exit 1
diff --git a/tools/linux/include/scripts/setup-centos6.sh b/tools/linux/include/scripts/setup-centos6.sh
index 4713b88415..463ef7f159 100644
--- a/tools/linux/include/scripts/setup-centos6.sh
+++ b/tools/linux/include/scripts/setup-centos6.sh
@@ -2,7 +2,7 @@
rm -f /etc/yum.repos.d/CentOS-Base.repo || exit 1
sed -i 's#baseurl=file:///media/CentOS/#baseurl=http://vault.centos.org/6.4/os/$basearch/#;s/enabled=0/enabled=1/;s/gpgcheck=1/gpgcheck=0/;/file:/d' /etc/yum.repos.d/CentOS-Media.repo || exit 1
-yum -y install make wget glibc-devel glibc-devel.i686 vixie-cron crontabs libxslt-devel pango-devel librsvg2-devel libxml2-devel unzip rsync git screen file tree bc gcc-c++ kernel-devel libX*devel fontconfig-devel freetype-devel zlib-devel *GL*devel *xcb*devel xorg*devel libdrm-devel mesa*devel *glut*devel dbus-devel xz patch bzip2-devel glib2-devel bison flex expat-devel libtool-ltdl-devel || exit 1
+yum -y install gettext make wget glibc-devel glibc-devel.i686 vixie-cron crontabs unzip rsync git screen file tree bc gcc-c++ kernel-devel libX*devel *GL*devel *xcb*devel xorg*devel libdrm-devel mesa*devel *glut*devel dbus-devel xz patch bison flex libtool-ltdl-devel || exit 1
chkconfig crond on
service crond start
From a3a9932f3664ed83bb4c873794e4e9dcd60a51f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?=
Date: Mon, 28 Sep 2015 07:12:33 +0200
Subject: [PATCH 009/178] Linux: sdk buildfix (missing depend)
---
tools/linux/common.sh | 1 +
tools/linux/include/scripts/build-sdk.sh | 15 ++++++++++++++-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/tools/linux/common.sh b/tools/linux/common.sh
index dee0ccdfb3..82c19af930 100644
--- a/tools/linux/common.sh
+++ b/tools/linux/common.sh
@@ -170,6 +170,7 @@ PANGO_TAR=pango-1.37.0.tar.xz
BZIP_TAR=bzip2-1.0.6.tar.gz
CROCO_TAR=libcroco-0.6.8.tar.xz
SVG_TAR=librsvg-2.40.10.tar.xz
+GDK_TAR=gdk-pixbuf-2.32.1.tar.xz
TC_GCC=4.8.5
TC_MPC=1.0.1
diff --git a/tools/linux/include/scripts/build-sdk.sh b/tools/linux/include/scripts/build-sdk.sh
index 9cec28b81d..5f50d9969e 100644
--- a/tools/linux/include/scripts/build-sdk.sh
+++ b/tools/linux/include/scripts/build-sdk.sh
@@ -156,7 +156,7 @@ if [ ! -f "$INSTALL_PATH/lib/libz.so.1" ]; then
fi
tar xvf "$SRC_PATH/$ZLIB_TAR" || exit 1
cd zlib* || exit 1
- env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" --enable-static --enable-shared || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" ./configure --prefix="$INSTALL_PATH" || exit 1
make -j${MKJOBS} || exit 1
make install || exit 1
fi
@@ -580,6 +580,19 @@ if [ ! -f "$INSTALL_PATH/lib/libcroco-0.6.so.3" ]; then
make install || exit 1
fi
+# Install gdk
+if [ ! -f "$INSTALL_PATH/lib/pkgconfig/gdk-pixbuf-2.0.pc" ]; then
+ cd "$TMP_PATH" || exit 1
+ if [ ! -f "$SRC_PATH/$GDK_TAR" ]; then
+ wget "$THIRD_PARTY_SRC_URL/$GDK_TAR" -O "$SRC_PATH/$GDK_TAR" || exit 1
+ fi
+ tar xvf "$SRC_PATH/$GDK_TAR" || exit 1
+ cd gdk-pix* || exit 1
+ env CFLAGS="$BF" CXXFLAGS="$BF" CPPFLAGS="-I${INSTALL_PATH}/include" LDFLAGS="-L${INSTALL_PATH}/lib" ./configure --prefix="$INSTALL_PATH" --disable-docs --enable-static --enable-shared || exit 1
+ make -j${MKJOBS} || exit 1
+ make install || exit 1
+fi
+
# Install svg
if [ ! -f "$INSTALL_PATH/lib/pkgconfig/librsvg-2.0.pc" ]; then
cd "$TMP_PATH" || exit 1
From 7892b81cb539bff08eb61e1ad2a8434db45d7330 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?=
Date: Mon, 28 Sep 2015 08:12:28 +0200
Subject: [PATCH 010/178] Linux: deploy libs changes
---
.../linux/include/scripts/build-installer.sh | 57 ++++++++++++++++++-
1 file changed, 54 insertions(+), 3 deletions(-)
diff --git a/tools/linux/include/scripts/build-installer.sh b/tools/linux/include/scripts/build-installer.sh
index c875a8293a..08dd5891b0 100644
--- a/tools/linux/include/scripts/build-installer.sh
+++ b/tools/linux/include/scripts/build-installer.sh
@@ -108,7 +108,20 @@ for y in $OFX_LIB_DEP; do
cp -v $y $IO_LIBS/ || exit 1
done
-rm -f $IO_LIBS/{libgcc*,libstdc*}
+rm -f $IO_LIBS/{libgcc*,libstdc*,libbz2*,libfont*,libfree*,libpng*,libjpeg*,libtiff*,libz.*}
+(cd $IO_LIBS ;
+ ln -sf ../../../lib/libbz2.so.1.0 .
+ ln -sf ../../../lib/libbz2.so.1 .
+ ln -sf ../../../lib/libfontconfig.so.1 .
+ ln -sf ../../../lib/libfreetype.so.6 .
+ ln -sf ../../../lib/libpng12.so.0 .
+ ln -sf ../../../lib/libjpeg.so.9 .
+ ln -sf ../../../lib/libtiff.so.5 .
+ ln -sf ../../../lib/libz.so.1 .
+ ln -sf ../../../lib/libgcc_s.so.1 .
+ ln -sf ../../../lib/libstdc++.so.6 .
+)
+strip -s $IO_LIBS/*
IO_LIC=$OFX_IO_PATH/meta/ofx-io-license.txt
echo "" >>$IO_LIC || exit 1
@@ -261,8 +274,19 @@ OFX_CIMG_DEPENDS=$(ldd $OFX_MISC_PATH/data/Plugins/*/*/*/*|grep opt | awk '{prin
for x in $OFX_CIMG_DEPENDS; do
cp -v $x $CIMG_LIBS/ || exit 1
done
-rm -f $CIMG_LIBS/{libgcc*,libstdc*}
+rm -f $CIMG_LIBS/{libgcc*,libstdc*,libgomp*}
+(cd $CIMG_LIBS ;
+ ln -sf ../../../lib/libgcc_s.so.1 .
+ ln -sf ../../../lib/libstdc++.so.6 .
+ ln -sf ../../../lib/libgomp.so.1 .
+)
strip -s $CIMG_LIBS/*
+MISC_LIBS=$OFX_MISC_PATH/data/Plugins/Misc.ofx.bundle/Libraries
+mkdir -p $MISC_LIBS || exit 1
+(cd $MISC_LIBS ;
+ ln -sf ../../../lib/libgcc_s.so.1 .
+ ln -sf ../../../lib/libstdc++.so.6 .
+)
# NATRON
NATRON_PATH=$INSTALLER/packages/$NATRON_PKG
@@ -323,6 +347,19 @@ if [ -f $INC_PATH/misc/compat${BIT}.tgz ]; then
tar xvf $INC_PATH/misc/compat${BIT}.tgz -C $CLIBS_PATH/data/lib/ || exit 1
fi
+cp $INSTALL_PATH/lib/{libicudata.so.55,libicui18n.so.55,libicuuc.so.55} $CLIBS_PATH/data/lib/ || exit 1
+(cd $CLIBS_PATH/data/lib;
+ rm -f libbz2.so.1.0
+ ln -sf libbz2.so.1 libbz2.so.1.0
+)
+
+mv $IO_LIBS/{libOpenColor*,libgomp*} $CLIBS_PATH/data/lib/ || exit 1
+(cd $IO_LIBS ;
+ ln -sf ../../../lib/libOpenColorIO.so.1 .
+ ln -sf ../../../lib/libgomp.so.1 .
+)
+
+
# TODO: At this point send unstripped binaries (and debug binaries?) to Socorro server for breakpad
strip -s $CLIBS_PATH/data/lib/*
@@ -388,8 +425,22 @@ OFX_ARENA_DEPENDS=$(ldd $OFX_ARENA_PATH/data/Plugins/*/*/*/*|grep opt | awk '{pr
for x in $OFX_ARENA_DEPENDS; do
cp -v $x $ARENA_LIBS/ || exit 1
done
+rm -f $ARENA_LIBS/{libgomp*,libOpenColorIO*,libbz2*,libfont*,libz.so*,libglib-2*,libgthread*,libpng*,libfree*,libexpat*,libgcc*,libstdc*}
+(cd $ARENA_LIBS ;
+ ln -sf ../../../lib/libbz2.so.1.0 .
+ ln -sf ../../../lib/libexpat.so.1 .
+ ln -sf ../../../lib/libfontconfig.so.1 .
+ ln -sf ../../../lib/libfreetype.so.6 .
+ ln -sf ../../../lib/libglib-2.0.so.0 .
+ ln -sf ../../../lib/libgthread-2.0.so.0 .
+ ln -sf ../../../lib/libpng12.so.0 .
+ ln -sf ../../../lib/libz.so.1 .
+ ln -sf ../../../lib/libgcc_s.so.1 .
+ ln -sf ../../../lib/libstdc++.so.6 .
+ ln -sf ../../../lib/libOpenColorIO.so.1 .
+ ln -sf ../../../lib/libgomp.so.1 .
+)
strip -s $ARENA_LIBS/*
-rm -f $ARENA_LIBS/{libcairo*,libgcc*,libstdc*}
# OFX CV
#OFX_CV_VERSION=$TAG
From de5e70152654157263732454105b80e82c39c206 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?=
Date: Mon, 28 Sep 2015 09:14:01 +0200
Subject: [PATCH 011/178] Linux: fontconfig
---
tools/linux/include/scripts/Natron.sh | 4 ++++
tools/linux/include/scripts/build-installer.sh | 3 +++
2 files changed, 7 insertions(+)
diff --git a/tools/linux/include/scripts/Natron.sh b/tools/linux/include/scripts/Natron.sh
index 58c7e0eec7..efc2d8b165 100644
--- a/tools/linux/include/scripts/Natron.sh
+++ b/tools/linux/include/scripts/Natron.sh
@@ -12,6 +12,10 @@ DIR=`cd -P "$SOURCEDIR" && pwd`
export LC_NUMERIC=C
+if [ -d "$DIR/Resources/etc/fonts" ]; then
+ export FONTCONFIG_PATH=$DIR/Resources/etc/fonts
+fi
+
if [ "$1" = "-update" -a -x "$DIR/NatronSetup" ]; then
"$DIR/NatronSetup" --updater
exit 0
diff --git a/tools/linux/include/scripts/build-installer.sh b/tools/linux/include/scripts/build-installer.sh
index 08dd5891b0..b8fe817ff2 100644
--- a/tools/linux/include/scripts/build-installer.sh
+++ b/tools/linux/include/scripts/build-installer.sh
@@ -359,6 +359,9 @@ mv $IO_LIBS/{libOpenColor*,libgomp*} $CLIBS_PATH/data/lib/ || exit 1
ln -sf ../../../lib/libgomp.so.1 .
)
+mkdir -p $CLIBS_PATH/data/share/etc || exit 1
+cp -a $INSTALL_PATH/etc/fonts $CLIBS_PATH/data/share/etc/ || exit 1
+(cd $CLIBS_PATH/data ; ln -sf share Resources )
# TODO: At this point send unstripped binaries (and debug binaries?) to Socorro server for breakpad
From 1ce4b8298559f63928d5c4a64a83d2589aa45bf0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?=
Date: Mon, 28 Sep 2015 09:15:11 +0200
Subject: [PATCH 012/178] AppManager: set fontconfig path on all platforms
---
Engine/AppManager.cpp | 19 +------------------
1 file changed, 1 insertion(+), 18 deletions(-)
diff --git a/Engine/AppManager.cpp b/Engine/AppManager.cpp
index 2eea4cf740..112b6ba1d8 100644
--- a/Engine/AppManager.cpp
+++ b/Engine/AppManager.cpp
@@ -149,23 +149,8 @@ AppManager::load(int &argc,
}
initializeQApp(argc, argv);
-#if defined(__NATRON_OSX__)
+ // set fontconfig path on all platforms
if (qgetenv("FONTCONFIG_PATH").isNull()) {
- // set FONTCONFIG_PATH to Natron.app/Contents/Resources/etc/fonts (required by plugins using fontconfig)
- QString path = QCoreApplication::applicationDirPath() + "/../Resources/etc/fonts";
- QString pathcfg = path + "/fonts.conf";
- // Note:
- // a minimalist fonts.conf file for OS X is:
- // /System/Library/Fonts/Library/Fonts~/Library/Fonts
- if (!QFile(pathcfg).exists()) {
- qWarning() << "Fontconfig configuration file" << pathcfg << "does not exist, not setting FONTCONFIG_PATH";
- } else {
- qDebug() << "Setting FONTCONFIG_PATH to" << path;
- qputenv("FONTCONFIG_PATH", path.toUtf8());
- }
- }
-#elif defined(__NATRON_WIN32__)
- if (qgetenv("FONTCONFIG_PATH").isNull()) {
// set FONTCONFIG_PATH to Natron/Resources/etc/fonts (required by plugins using fontconfig)
QString path = QCoreApplication::applicationDirPath() + "/../Resources/etc/fonts";
QString pathcfg = path + "/fonts.conf";
@@ -176,8 +161,6 @@ AppManager::load(int &argc,
qputenv("FONTCONFIG_PATH", path.toUtf8());
}
}
-#endif
-
initPython(argc, argv);
From eb79712772ee35739dbb5c4d3cbbbbf33840b184 Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Mon, 28 Sep 2015 09:27:10 +0200
Subject: [PATCH 013/178] Dopesheet: handle recursion in frame range
computation. Also try catch exception
---
Engine/AppManager.cpp | 8 +++--
Engine/Node.cpp | 5 ++-
Engine/NodeWrapper.cpp | 2 +-
Gui/DopeSheetView.cpp | 75 ++++++++++++++++++++++++++++++++++++++++--
4 files changed, 84 insertions(+), 6 deletions(-)
diff --git a/Engine/AppManager.cpp b/Engine/AppManager.cpp
index 2eea4cf740..7cb61d9160 100644
--- a/Engine/AppManager.cpp
+++ b/Engine/AppManager.cpp
@@ -178,8 +178,12 @@ AppManager::load(int &argc,
}
#endif
-
- initPython(argc, argv);
+ try {
+ initPython(argc, argv);
+ } catch (const std::runtime_error& e) {
+ std::cerr << e.what() << std::endl;
+ return false;
+ }
_imp->idealThreadCount = QThread::idealThreadCount();
QThreadPool::globalInstance()->setExpiryTimeout(-1); //< make threads never exit on their own
diff --git a/Engine/Node.cpp b/Engine/Node.cpp
index 0a22ea783d..cb3d0df690 100644
--- a/Engine/Node.cpp
+++ b/Engine/Node.cpp
@@ -2362,11 +2362,14 @@ Node::makeCacheInfo() const
std::string
Node::makeInfoForInput(int inputNumber) const
{
+ if (inputNumber < 0 || inputNumber >= getMaxInputCount()) {
+ return "";
+ }
const Natron::Node* inputNode = 0;
std::string inputName ;
if (inputNumber != -1) {
inputNode = getInput(inputNumber).get();
- inputName = _imp->liveInstance->getInputLabel(inputNumber);
+ inputName = getInputLabel(inputNumber);
} else {
inputNode = this;
inputName = "Output";
diff --git a/Engine/NodeWrapper.cpp b/Engine/NodeWrapper.cpp
index 7406071c2c..d77ee1846e 100644
--- a/Engine/NodeWrapper.cpp
+++ b/Engine/NodeWrapper.cpp
@@ -144,7 +144,7 @@ Effect::getInputLabel(int inputNumber)
try {
return _node->getInputLabel(inputNumber);
} catch (const std::exception& e) {
- std::cout << e.what() << std::endl;
+ _node->getApp()->appendToScriptEditor(e.what());
}
return std::string();
}
diff --git a/Gui/DopeSheetView.cpp b/Gui/DopeSheetView.cpp
index 65738a1bc5..33fc015c9e 100644
--- a/Gui/DopeSheetView.cpp
+++ b/Gui/DopeSheetView.cpp
@@ -261,6 +261,8 @@ class DopeSheetViewPrivate
//
std::map nodeRanges;
+ std::list nodeRangesBeingComputed; // to avoid recursion in groups
+ int rangeComputationRecursion;
// for rendering
QFont *font;
@@ -308,6 +310,8 @@ DopeSheetViewPrivate::DopeSheetViewPrivate(DopeSheetView *qq) :
gui(0),
timeline(),
nodeRanges(),
+ nodeRangesBeingComputed(),
+ rangeComputationRecursion(0),
font(new QFont(appFont,appFontSize)),
textRenderer(),
kfTexturesIDs(),
@@ -1808,6 +1812,13 @@ void DopeSheetViewPrivate::computeNodeRange(DSNode *dsNode)
void DopeSheetViewPrivate::computeReaderRange(DSNode *reader)
{
+ if (std::find(nodeRangesBeingComputed.begin(), nodeRangesBeingComputed.end(), reader) != nodeRangesBeingComputed.end()) {
+ return;
+ }
+
+ nodeRangesBeingComputed.push_back(reader);
+ ++rangeComputationRecursion;
+
NodePtr node = reader->getInternalNode();
Knob *startingTimeKnob = dynamic_cast *>(node->getKnobByName(kReaderParamNameStartingTime).get());
@@ -1833,10 +1844,23 @@ void DopeSheetViewPrivate::computeReaderRange(DSNode *reader)
if (boost::shared_ptr isConnectedToTimeNode = model->getNearestTimeNodeFromOutputs(reader)) {
computeNodeRange(isConnectedToTimeNode.get());
}
+
+ --rangeComputationRecursion;
+ std::list::iterator found = std::find(nodeRangesBeingComputed.begin(), nodeRangesBeingComputed.end(), reader);
+ assert(found != nodeRangesBeingComputed.end());
+ nodeRangesBeingComputed.erase(found);
}
void DopeSheetViewPrivate::computeRetimeRange(DSNode *retimer)
{
+
+ if (std::find(nodeRangesBeingComputed.begin(), nodeRangesBeingComputed.end(), retimer) != nodeRangesBeingComputed.end()) {
+ return;
+ }
+
+ nodeRangesBeingComputed.push_back(retimer);
+ ++rangeComputationRecursion;
+
NodePtr node = retimer->getInternalNode();
NodePtr input = node->getInput(0);
if (input) {
@@ -1870,10 +1894,23 @@ void DopeSheetViewPrivate::computeRetimeRange(DSNode *retimer)
else {
nodeRanges[retimer] = FrameRange();
}
+
+ --rangeComputationRecursion;
+ std::list::iterator found = std::find(nodeRangesBeingComputed.begin(), nodeRangesBeingComputed.end(), retimer);
+ assert(found != nodeRangesBeingComputed.end());
+ nodeRangesBeingComputed.erase(found);
}
void DopeSheetViewPrivate::computeTimeOffsetRange(DSNode *timeOffset)
{
+
+ if (std::find(nodeRangesBeingComputed.begin(), nodeRangesBeingComputed.end(), timeOffset) != nodeRangesBeingComputed.end()) {
+ return;
+ }
+
+ nodeRangesBeingComputed.push_back(timeOffset);
+ ++rangeComputationRecursion;
+
FrameRange range(0, 0);
// Retrieve nearest reader useful values
@@ -1891,10 +1928,23 @@ void DopeSheetViewPrivate::computeTimeOffsetRange(DSNode *timeOffset)
}
nodeRanges[timeOffset] = range;
+
+ --rangeComputationRecursion;
+ std::list::iterator found = std::find(nodeRangesBeingComputed.begin(), nodeRangesBeingComputed.end(), timeOffset);
+ assert(found != nodeRangesBeingComputed.end());
+ nodeRangesBeingComputed.erase(found);
}
void DopeSheetViewPrivate::computeFRRange(DSNode *frameRange)
{
+
+ if (std::find(nodeRangesBeingComputed.begin(), nodeRangesBeingComputed.end(), frameRange) != nodeRangesBeingComputed.end()) {
+ return;
+ }
+
+ nodeRangesBeingComputed.push_back(frameRange);
+ ++rangeComputationRecursion;
+
NodePtr node = frameRange->getInternalNode();
Knob *frameRangeKnob = dynamic_cast *>(node->getKnobByName("frameRange").get());
@@ -1905,24 +1955,39 @@ void DopeSheetViewPrivate::computeFRRange(DSNode *frameRange)
range.second = frameRangeKnob->getValue(1);
nodeRanges[frameRange] = range;
+
+ --rangeComputationRecursion;
+ std::list::iterator found = std::find(nodeRangesBeingComputed.begin(), nodeRangesBeingComputed.end(), frameRange);
+ assert(found != nodeRangesBeingComputed.end());
+ nodeRangesBeingComputed.erase(found);
}
void DopeSheetViewPrivate::computeGroupRange(DSNode *group)
{
+
+ if (std::find(nodeRangesBeingComputed.begin(), nodeRangesBeingComputed.end(), group) != nodeRangesBeingComputed.end()) {
+ return;
+ }
+
NodePtr node = group->getInternalNode();
assert(node);
if (!node) {
throw std::logic_error("DopeSheetViewPrivate::computeGroupRange: node is NULL");
}
-
+
FrameRange range;
std::set times;
-
+
NodeGroup* nodegroup = dynamic_cast(node->getLiveInstance());
assert(nodegroup);
if (!nodegroup) {
throw std::logic_error("DopeSheetViewPrivate::computeGroupRange: node is not a group");
}
+
+ nodeRangesBeingComputed.push_back(group);
+ ++rangeComputationRecursion;
+
+
NodeList nodes = nodegroup->getNodes();
for (NodeList::const_iterator it = nodes.begin(); it != nodes.end(); ++it) {
@@ -1984,6 +2049,12 @@ void DopeSheetViewPrivate::computeGroupRange(DSNode *group)
}
nodeRanges[group] = range;
+
+ --rangeComputationRecursion;
+ std::list::iterator found = std::find(nodeRangesBeingComputed.begin(), nodeRangesBeingComputed.end(), group);
+ assert(found != nodeRangesBeingComputed.end());
+ nodeRangesBeingComputed.erase(found);
+
}
void DopeSheetViewPrivate::onMouseLeftButtonDrag(QMouseEvent *e)
From be4258463d048b42072164808546977b97a4cd56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?=
Date: Mon, 28 Sep 2015 09:27:30 +0200
Subject: [PATCH 014/178] Linux: add missing symlink in installer
---
tools/linux/include/scripts/build-installer.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/linux/include/scripts/build-installer.sh b/tools/linux/include/scripts/build-installer.sh
index b8fe817ff2..95ee3cd73d 100644
--- a/tools/linux/include/scripts/build-installer.sh
+++ b/tools/linux/include/scripts/build-installer.sh
@@ -431,6 +431,7 @@ done
rm -f $ARENA_LIBS/{libgomp*,libOpenColorIO*,libbz2*,libfont*,libz.so*,libglib-2*,libgthread*,libpng*,libfree*,libexpat*,libgcc*,libstdc*}
(cd $ARENA_LIBS ;
ln -sf ../../../lib/libbz2.so.1.0 .
+ ln -sf ../../../lib/libbz2.so.1 .
ln -sf ../../../lib/libexpat.so.1 .
ln -sf ../../../lib/libfontconfig.so.1 .
ln -sf ../../../lib/libfreetype.so.6 .
From a9dc15b878d837237d7f8a576667641b4bac040e Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Mon, 28 Sep 2015 09:43:59 +0200
Subject: [PATCH 015/178] Fix #921
---
Gui/Edge.cpp | 8 +++++++-
Gui/NodeGraph20.cpp | 7 ++++---
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/Gui/Edge.cpp b/Gui/Edge.cpp
index 86cdcc0f0e..7fa005424d 100644
--- a/Gui/Edge.cpp
+++ b/Gui/Edge.cpp
@@ -198,7 +198,13 @@ Edge::setSourceAndDestination(const boost::shared_ptr & src,
}
if (!_label) {
- _label = new QGraphicsTextItem(QString( dst->getNode()->getInputLabel(_inputNb).c_str() ),this);
+ QString label;
+ try {
+ label = QString( dst->getNode()->getInputLabel(_inputNb).c_str() );
+ } catch (...) {
+
+ }
+ _label = new QGraphicsTextItem(label,this);
_label->setDefaultTextColor( QColor(200,200,200) );
} else {
_label->setPlainText( QString( dst->getNode()->getInputLabel(_inputNb).c_str() ) );
diff --git a/Gui/NodeGraph20.cpp b/Gui/NodeGraph20.cpp
index 892457b7df..219f24b7b1 100644
--- a/Gui/NodeGraph20.cpp
+++ b/Gui/NodeGraph20.cpp
@@ -228,7 +228,7 @@ NodeGraph::mouseMoveEvent(QMouseEvent* e)
boost::shared_ptr nodeToShowMergeRect;
boost::shared_ptr selectedNodeInternalNode = selectedNode->getNode();
- bool selectedNodeIsReader = selectedNodeInternalNode->getLiveInstance()->isReader();
+ bool selectedNodeIsReader = selectedNodeInternalNode->getLiveInstance()->isReader() || selectedNodeInternalNode->getMaxInputCount() == 0;
Edge* edge = 0;
{
QMutexLocker l(&_imp->_nodesMutex);
@@ -312,7 +312,8 @@ NodeGraph::mouseMoveEvent(QMouseEvent* e)
if ( edge && !edge->isOutputEdge() ) {
- if ((*it)->getNode()->getLiveInstance()->isReader()) {
+ if ((*it)->getNode()->getLiveInstance()->isReader() ||
+ (*it)->getNode()->getMaxInputCount() == 0) {
edge = 0;
continue;
}
@@ -324,7 +325,7 @@ NodeGraph::mouseMoveEvent(QMouseEvent* e)
Natron::Node::CanConnectInputReturnValue ret = edge->getDest()->getNode()->canConnectInput(selectedNodeInternalNode, edge->getInputNumber());
if (ret == Natron::Node::eCanConnectInput_inputAlreadyConnected &&
- !selectedNodeInternalNode->getLiveInstance()->isReader()) {
+ !selectedNodeIsReader) {
ret = Natron::Node::eCanConnectInput_ok;
}
From 1cd0c193de3d11283c106b99facc7ceb1f067642 Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Mon, 28 Sep 2015 16:02:14 +0200
Subject: [PATCH 016/178] Clean up code of all data depending on the graph
state (clip preferences, draft state etc...)
---
Engine/AppInstance.cpp | 20 +-
Engine/AppManager.cpp | 5 +-
Engine/AppManager.h | 3 +-
Engine/EffectInstance.cpp | 38 +--
Engine/EffectInstance.h | 36 +--
Engine/EffectInstanceRenderRoI.cpp | 2 +-
Engine/Engine.pro | 2 +-
Engine/Node.cpp | 433 ++++++++++++++++++++++-------
Engine/Node.h | 27 +-
Engine/NodeGroup.cpp | 4 +-
Engine/NodeGroup.h | 2 +-
Engine/OfxEffectInstance.cpp | 164 +++--------
Engine/OfxEffectInstance.h | 9 +-
Engine/OfxHost.cpp | 5 +-
Engine/OfxHost.h | 3 +-
Engine/OfxImageEffectInstance.cpp | 29 +-
Engine/OfxImageEffectInstance.h | 2 +-
Engine/ParallelRenderArgs.cpp | 7 +
Engine/Project.cpp | 4 +-
Engine/ProjectPrivate.cpp | 2 +-
Engine/ViewerInstance.cpp | 19 +-
Engine/ViewerInstance.h | 6 +-
Gui/Gui.cpp | 8 +-
Gui/Gui.h | 5 +-
Gui/GuiAppInstance.cpp | 40 ++-
Gui/NodeGraph.cpp | 20 +-
Gui/NodeGraph.h | 7 +-
Gui/NodeGraph05.cpp | 13 +-
28 files changed, 538 insertions(+), 377 deletions(-)
diff --git a/Engine/AppInstance.cpp b/Engine/AppInstance.cpp
index 418eac6ec3..b60cda406c 100644
--- a/Engine/AppInstance.cpp
+++ b/Engine/AppInstance.cpp
@@ -1387,17 +1387,17 @@ AppInstance::getAppIDString() const
}
void
-AppInstance::onGroupCreationFinished(const boost::shared_ptr& /*node*/)
+AppInstance::onGroupCreationFinished(const boost::shared_ptr& node)
{
-// assert(node);
-// if (!_imp->_currentProject->isLoadingProject()) {
-// NodeGroup* isGrp = dynamic_cast(node->getLiveInstance());
-// assert(isGrp);
-// if (!isGrp) {
-// return;
-// }
-// isGrp->forceGetClipPreferencesOnAllTrees();
-// }
+ assert(node);
+ if (!_imp->_currentProject->isLoadingProject()) {
+ NodeGroup* isGrp = dynamic_cast(node->getLiveInstance());
+ assert(isGrp);
+ if (!isGrp) {
+ return;
+ }
+ isGrp->forceComputeInputDependentDataOnAllTrees();
+ }
}
bool
diff --git a/Engine/AppManager.cpp b/Engine/AppManager.cpp
index a8f2c2c816..27669ff96d 100644
--- a/Engine/AppManager.cpp
+++ b/Engine/AppManager.cpp
@@ -1464,9 +1464,10 @@ AppManager::createOFXEffect(boost::shared_ptr node,
const NodeSerialization* serialization,
const std::list >& paramValues,
bool allowFileDialogs,
- bool disableRenderScaleSupport) const
+ bool disableRenderScaleSupport,
+ bool *hasUsedFileDialog) const
{
- return _imp->ofxHost->createOfxEffect(node,serialization,paramValues,allowFileDialogs,disableRenderScaleSupport);
+ return _imp->ofxHost->createOfxEffect(node,serialization,paramValues,allowFileDialogs,disableRenderScaleSupport,hasUsedFileDialog);
}
void
diff --git a/Engine/AppManager.h b/Engine/AppManager.h
index d3ede33601..9538c81c4c 100644
--- a/Engine/AppManager.h
+++ b/Engine/AppManager.h
@@ -166,7 +166,8 @@ class AppManager
const NodeSerialization* serialization,
const std::list >& paramValues,
bool allowFileDialogs,
- bool disableRenderScaleSupport) const;
+ bool disableRenderScaleSupport,
+ bool *hasUsedFileDialog) const;
void registerAppInstance(AppInstance* app);
diff --git a/Engine/EffectInstance.cpp b/Engine/EffectInstance.cpp
index 73dfb69eeb..21054840e6 100644
--- a/Engine/EffectInstance.cpp
+++ b/Engine/EffectInstance.cpp
@@ -3002,11 +3002,7 @@ EffectInstance::isIdentity_public(bool useIdentityCache, // only set to true whe
void
EffectInstance::onInputChanged(int /*inputNo*/)
{
- if ( !getApp()->getProject()->isLoadingProject() ) {
- RenderScale s;
- s.x = s.y = 1.;
- checkOFXClipPreferences_public(getCurrentTime(), s, kOfxChangeUserEdited, true, true);
- }
+
}
Natron::StatusEnum
@@ -4117,11 +4113,6 @@ EffectInstance::getNearestNonIdentity(double time)
}
}
-void
-EffectInstance::restoreClipPreferences()
-{
- setSupportsRenderScaleMaybe(eSupportsYes);
-}
void
EffectInstance::onNodeHashChanged(U64 hash)
@@ -4276,33 +4267,6 @@ EffectInstance::getPreferredFrameRate() const
return getApp()->getProjectFrameRate();
}
-void
-EffectInstance::refreshChannelSelectors_recursiveInternal(Natron::Node* node,
- std::list & markedNodes)
-{
- std::list::iterator found = std::find(markedNodes.begin(), markedNodes.end(), node);
-
- if ( found != markedNodes.end() ) {
- return;
- }
- node->refreshChannelSelectors(false);
-
- markedNodes.push_back(node);
- std::list outputs;
- node->getOutputsWithGroupRedirection(outputs);
- for (std::list::const_iterator it = outputs.begin(); it != outputs.end(); ++it) {
- refreshChannelSelectors_recursiveInternal( (*it), markedNodes );
- }
-}
-
-void
-EffectInstance::refreshChannelSelectors_recursive()
-{
- std::list markedNodes;
-
- refreshChannelSelectors_recursiveInternal(getNode().get(), markedNodes);
-}
-
void
EffectInstance::checkOFXClipPreferences_recursive(double time,
const RenderScale & scale,
diff --git a/Engine/EffectInstance.h b/Engine/EffectInstance.h
index 65f7e8b56e..32c6ff4135 100644
--- a/Engine/EffectInstance.h
+++ b/Engine/EffectInstance.h
@@ -673,11 +673,17 @@ class EffectInstance
bool forceGetClipPrefAction,
bool recurse);
- void refreshChannelSelectors_recursive();
-
virtual void onChannelsSelectorRefreshed() {}
+ virtual bool checkOFXClipPreferences(double /*time*/,
+ const RenderScale & /*scale*/,
+ const std::string & /*reason*/,
+ bool /*forceGetClipPrefAction*/)
+ {
+ return false;
+ }
+
protected:
void checkOFXClipPreferences_recursive(double time,
@@ -686,12 +692,6 @@ class EffectInstance
bool forceGetClipPrefAction,
std::list & markedNodes);
- virtual void checkOFXClipPreferences(double /*time*/,
- const RenderScale & /*scale*/,
- const std::string & /*reason*/,
- bool /*forceGetClipPrefAction*/)
- {
- }
public:
@@ -907,9 +907,6 @@ class EffectInstance
virtual void aboutToRestoreDefaultValues() OVERRIDE FINAL;
virtual bool shouldCacheOutput(bool isFrameVaryingOrAnimated) const;
-protected:
-
-
/**
* @brief Can be derived to get the region that the plugin is capable of filling.
* This is meaningful for plugins that generate images or transform images.
@@ -917,8 +914,13 @@ class EffectInstance
* @param isProjectFormat[out] If set to true, then rod is taken to be equal to the current project format.
* In case of failure the plugin should return eStatusFailed.
* @returns eStatusOK, eStatusReplyDefault, or eStatusFailed. rod is set except if return value is eStatusOK or eStatusReplyDefault.
- **/
+ **/
virtual Natron::StatusEnum getRegionOfDefinition(U64 hash, double time, const RenderScale & scale, int view, RectD* rod) WARN_UNUSED_RETURN;
+
+protected:
+
+
+
virtual void calcDefaultRegionOfDefinition(U64 hash, double time, int view, const RenderScale & scale, RectD *rod);
/**
@@ -1189,11 +1191,6 @@ class EffectInstance
**/
virtual void onInputChanged(int inputNo);
- /**
- * @brief Called after the project has restored all nodes and their links, to set clip preferences.
- **/
- virtual void restoreClipPreferences();
-
/**
* @brief If the plug-in calls timelineGoTo and we're during a render/instance changed action,
* then all the knobs will retrieve the current time as being the one in the last render args thread-storage.
@@ -1816,10 +1813,7 @@ class EffectInstance
**/
int getInputNumber(Natron::EffectInstance* inputEffect) const;
-protected:
- static void
- refreshChannelSelectors_recursiveInternal(Natron::Node* node,
- std::list & markedNodes);
+
};
diff --git a/Engine/EffectInstanceRenderRoI.cpp b/Engine/EffectInstanceRenderRoI.cpp
index b3c061e9b0..f194fab81f 100644
--- a/Engine/EffectInstanceRenderRoI.cpp
+++ b/Engine/EffectInstanceRenderRoI.cpp
@@ -605,7 +605,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////// End Compute RoI /////////////////////////////////////////////////////////////////////////
- bool draftModeSupported = supportsRenderQuality();
+ bool draftModeSupported = getNode()->isDraftModeUsed();
bool isFrameVaryingOrAnimated = isFrameVaryingOrAnimated_Recursive();
bool createInCache = shouldCacheOutput(isFrameVaryingOrAnimated);
diff --git a/Engine/Engine.pro b/Engine/Engine.pro
index 04fdd8d013..197b5db5c9 100644
--- a/Engine/Engine.pro
+++ b/Engine/Engine.pro
@@ -72,7 +72,7 @@ win32-msvc* {
# XCode clang 3.5 without optimization generates code that crashes
#(Natron on OSX, XCode 6, Spaceship_Natron.ntp)
*-xcode {
- #QMAKE_CXXFLAGS += -O1
+ QMAKE_CXXFLAGS += -O1
}
SOURCES += \
diff --git a/Engine/Node.cpp b/Engine/Node.cpp
index cb3d0df690..4109cd6bae 100644
--- a/Engine/Node.cpp
+++ b/Engine/Node.cpp
@@ -269,6 +269,8 @@ struct Node::Implementation
, currentSupportTiles(false)
, currentSupportOpenGLRender(Natron::ePluginOpenGLRenderSupportNone)
, currentSupportSequentialRender(Natron::eSequentialPreferenceNotSequential)
+ , draftModeUsed(false)
+ , mustComputeInputRelatedData(true)
, duringPaintStrokeCreation(false)
, lastStrokeMovementMutex()
, lastStrokeMovementBbox()
@@ -325,6 +327,7 @@ struct Node::Implementation
bool getSelectedLayer(int inputNb,const ChannelSelector& selector, ImageComponents* comp) const;
+
Node* _publicInterface;
boost::weak_ptr group;
@@ -483,6 +486,8 @@ struct Node::Implementation
bool currentSupportTiles;
Natron::PluginOpenGLRenderSupport currentSupportOpenGLRender;
Natron::SequentialPreferenceEnum currentSupportSequentialRender;
+ bool draftModeUsed,mustComputeInputRelatedData;
+
bool duringPaintStrokeCreation; // protected by lastStrokeMovementMutex
mutable QMutex lastStrokeMovementMutex;
@@ -499,6 +504,7 @@ struct Node::Implementation
bool useAlpha0ToConvertFromRGBToRGBA;
bool isBeingDestroyed;
+
};
/**
@@ -606,7 +612,7 @@ Node::load(const std::string & parentMultiInstanceName,
}
}
-
+ bool hasUsedFileDialog = false;
if (func.first) {
_imp->liveInstance.reset(func.second(thisShared));
assert(_imp->liveInstance);
@@ -631,6 +637,7 @@ Node::load(const std::string & parentMultiInstanceName,
images = getApp()->saveImageFileDialog();
}
if (!images.empty()) {
+ hasUsedFileDialog = true;
boost::shared_ptr defaultFile = createDefaultValueForParam(kOfxImageEffectFileParamName, images);
CreateNodeArgs::DefaultValuesList list;
list.push_back(defaultFile);
@@ -638,7 +645,7 @@ Node::load(const std::string & parentMultiInstanceName,
}
} else { //ofx plugin
- _imp->liveInstance = appPTR->createOFXEffect(thisShared,&serialization,paramValues,!isFileDialogPreviewReader && userEdited,renderScaleSupportPreference == 1);
+ _imp->liveInstance = appPTR->createOFXEffect(thisShared,&serialization,paramValues,!isFileDialogPreviewReader && userEdited,renderScaleSupportPreference == 1, &hasUsedFileDialog);
assert(_imp->liveInstance);
_imp->liveInstance->initializeOverlayInteract();
}
@@ -717,10 +724,31 @@ Node::load(const std::string & parentMultiInstanceName,
_imp->nodeCreated = true;
- refreshChannelSelectors(serialization.isNull());
+ refreshAllInputRelatedData(serialization.isNull());
_imp->runOnNodeCreatedCB(serialization.isNull());
+
+ ///Now that the instance is created, make sure instanceChangedActino is called for all extra default values
+ ///that we set
+ for (std::list >::const_iterator it = paramValues.begin(); it != paramValues.end(); ++it) {
+ boost::shared_ptr knob = getKnobByName((*it)->getName());
+ if (knob) {
+ for (int i = 0; i < knob->getDimension(); ++i) {
+ knob->evaluateValueChange(i, Natron::eValueChangedReasonUserEdited);
+ }
+ } else {
+ qDebug() << "WARNING: No such parameter " << (*it)->getName().c_str();
+ }
+ }
+
+ if (hasUsedFileDialog) {
+ boost::shared_ptr fileNameKnob = getKnobByName(kOfxImageEffectFileParamName);
+ if (fileNameKnob) {
+ fileNameKnob->evaluateValueChange(0,Natron::eValueChangedReasonUserEdited);
+ }
+ }
+
} // load
bool
@@ -5167,7 +5195,7 @@ Node::findClosestInList(const Natron::ImageComponents& comp,
} else {
int diff = it->getNumComponents() - comp.getNumComponents();
int diffSoFar = closestComp->getNumComponents() - comp.getNumComponents();
- if (diff > diffSoFar) {
+ if (diff > diffSoFar && diffSoFar != 0) {
closestComp = it;
}
}
@@ -5318,32 +5346,51 @@ Node::onInputChanged(int inputNb)
}
assert( QThread::currentThread() == qApp->thread() );
_imp->duringInputChangedAction = true;
- std::map::iterator found = _imp->maskSelectors.find(inputNb);
- boost::shared_ptr inp = getInput(inputNb);
- if ( found != _imp->maskSelectors.end() ) {
- boost::shared_ptr enabled = found->second.enabled.lock();
- assert(enabled);
- enabled->blockValueChanges();
- enabled->setValue(inp ? true : false, 0);
- enabled->unblockValueChanges();
+
+ refreshMaskEnabledNess(inputNb);
+ refreshLayersChoiceSecretness(inputNb);
+ refreshDynamicProperties();
+
+ ViewerInstance* isViewer = dynamic_cast(_imp->liveInstance.get());
+ if (isViewer) {
+ isViewer->refreshActiveInputs(inputNb);
}
- std::map::iterator foundChan = _imp->channelsSelectors.find(inputNb);
- if ( foundChan != _imp->channelsSelectors.end() ) {
- std::map::iterator foundOuptut = _imp->channelsSelectors.find(-1);
- bool outputIsAll = false;
- if (foundOuptut != _imp->channelsSelectors.end()) {
- boost::shared_ptr outputChoice = foundOuptut->second.layer.lock();
- if (outputChoice) {
- outputIsAll = outputChoice->getActiveEntryText_mt_safe() == "All";
- }
- }
- boost::shared_ptr chanChoice = foundChan->second.layer.lock();
- if (chanChoice) {
- chanChoice->setSecret(!inp.get() || outputIsAll);
- }
+
+
+ if (!getApp()->getProject()->isLoadingProject() && !getApp()->isCreatingPythonGroup()) {
+
+ ///When loading a group (or project) just wait until everything is setup to actually compute input
+ ///related data such as clip preferences
+
+ /**
+ * The plug-in might call getImage, set a valid thread storage on the tree.
+ **/
+ double time = getApp()->getTimeLine()->currentFrame();
+ ParallelRenderArgsSetter frameRenderArgs(getApp()->getProject().get(),
+ time,
+ 0 /*view*/,
+ true,
+ false,
+ false,
+ 0,
+ shared_from_this(),
+ 0,
+ 0, //texture index
+ getApp()->getTimeLine().get(),
+ NodePtr(),
+ false,
+ false,
+ false,
+ boost::shared_ptr());
+
+
+ ///Don't do clip preferences while loading a project, they will be refreshed globally once the project is loaded.
+
+ _imp->liveInstance->onInputChanged(inputNb);
+
+ forceRefreshAllInputRelatedData();
}
- _imp->liveInstance->onInputChanged(inputNb);
- _imp->liveInstance->refreshChannelSelectors_recursive();
+
_imp->duringInputChangedAction = false;
}
@@ -6484,6 +6531,232 @@ Node::shouldCacheOutput(bool isFrameVaryingOrAnimated) const
}
+bool
+Node::refreshLayersChoiceSecretness(int inputNb)
+{
+ std::map::iterator foundChan = _imp->channelsSelectors.find(inputNb);
+ boost::shared_ptr inp = getInput(inputNb);
+ if ( foundChan != _imp->channelsSelectors.end() ) {
+ std::map::iterator foundOuptut = _imp->channelsSelectors.find(-1);
+ bool outputIsAll = false;
+ if (foundOuptut != _imp->channelsSelectors.end()) {
+ boost::shared_ptr outputChoice = foundOuptut->second.layer.lock();
+ if (outputChoice) {
+ outputIsAll = outputChoice->getActiveEntryText_mt_safe() == "All";
+ }
+ }
+ boost::shared_ptr chanChoice = foundChan->second.layer.lock();
+ if (chanChoice) {
+ bool isSecret = chanChoice->getIsSecret();
+ bool mustBeSecret = !inp.get() || outputIsAll;
+ bool changed = isSecret != mustBeSecret;
+ if (changed) {
+ chanChoice->setSecret(mustBeSecret);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool
+Node::refreshMaskEnabledNess(int inputNb)
+{
+ std::map::iterator found = _imp->maskSelectors.find(inputNb);
+ boost::shared_ptr inp = getInput(inputNb);
+ bool changed = false;
+ if ( found != _imp->maskSelectors.end() ) {
+ boost::shared_ptr enabled = found->second.enabled.lock();
+ assert(enabled);
+ enabled->blockValueChanges();
+ bool curValue = enabled->getValue();
+ bool newValue = inp ? true : false;
+ changed = curValue != newValue;
+ if (changed) {
+ enabled->setValue(newValue, 0);
+ }
+ enabled->unblockValueChanges();
+ }
+ return changed;
+}
+
+bool
+Node::refreshDraftFlagInternal(const std::vector >& inputs)
+{
+ bool hasDraftInput = false;
+ for (std::size_t i = 0; i < inputs.size(); ++i) {
+ if (inputs[i]) {
+ hasDraftInput |= inputs[i]->isDraftModeUsed();
+ }
+ }
+ hasDraftInput |= _imp->liveInstance->supportsRenderQuality();
+ bool changed;
+ {
+ QMutexLocker k(&_imp->pluginsPropMutex);
+ changed = _imp->draftModeUsed != hasDraftInput;
+ _imp->draftModeUsed = hasDraftInput;
+ }
+ return changed;
+}
+
+void
+Node::refreshAllInputRelatedData(bool canChangeValues)
+{
+ refreshAllInputRelatedData(canChangeValues,getInputs_copy());
+}
+
+bool
+Node::refreshAllInputRelatedData(bool canChangeValues,const std::vector >& inputs)
+{
+ bool hasChanged = false;
+ hasChanged |= refreshDraftFlagInternal(inputs);
+
+ ///if all non optional clips are connected, call getClipPrefs
+ ///The clip preferences action is never called until all non optional clips have been attached to the plugin.
+ if (!hasMandatoryInputDisconnected()) {
+
+ if (getApp()->getProject()->isLoadingProject()) {
+ //Nb: we clear the action cache because when creating the node many calls to getRoD and stuff might have returned
+ //empty rectangles, but since we force the hash to remain what was in the project file, we might then get wrong RoDs returned
+ _imp->liveInstance->clearActionsCache();
+ }
+
+ double time = (double)getApp()->getTimeLine()->currentFrame();
+
+ RenderScale scaleOne;
+ scaleOne.x = scaleOne.y = 1.;
+ ///Render scale support might not have been set already because getRegionOfDefinition could have failed until all non optional inputs were connected
+ if (_imp->liveInstance->supportsRenderScaleMaybe() == EffectInstance::eSupportsMaybe) {
+ RectD rod;
+
+ Natron::StatusEnum stat = _imp->liveInstance->getRegionOfDefinition(getHashValue(), time, scaleOne, 0, &rod);
+ if (stat != eStatusFailed) {
+ RenderScale scale;
+ scale.x = 0.5;
+ scale.y = 0.5;
+ stat = _imp->liveInstance->getRegionOfDefinition(getHashValue(), time, scale, 0, &rod);
+ if (stat != eStatusFailed) {
+ _imp->liveInstance->setSupportsRenderScaleMaybe(EffectInstance::eSupportsYes);
+ } else {
+ _imp->liveInstance->setSupportsRenderScaleMaybe(EffectInstance::eSupportsNo);
+ }
+ }
+
+ }
+ hasChanged |= _imp->liveInstance->checkOFXClipPreferences(time, scaleOne, kOfxChangeUserEdited, true);
+ }
+
+ hasChanged |= refreshChannelSelectors(canChangeValues);
+
+ return hasChanged;
+}
+
+bool
+Node::refreshInputRelatedDataInternal(std::list& markedNodes)
+{
+ {
+ QMutexLocker k(&_imp->pluginsPropMutex);
+ if (!_imp->mustComputeInputRelatedData) {
+ //We didn't change
+ return false;
+ }
+ }
+
+ std::list::iterator found = std::find(markedNodes.begin(), markedNodes.end(), this);
+ if (found != markedNodes.end()) {
+ return false;
+ }
+
+ ///Check if inputs must be refreshed first
+
+ int maxInputs = getMaxInputCount();
+ std::vector inputsCopy(maxInputs);
+ for (int i = 0; i < maxInputs; ++i) {
+ inputsCopy[i] = getInput(i);
+ if (inputsCopy[i] && inputsCopy[i]->isInputRelatedDataDirty()) {
+ inputsCopy[i]->refreshInputRelatedDataInternal(markedNodes);
+ }
+ }
+
+
+ markedNodes.push_back(this);
+
+ bool hasChanged = refreshAllInputRelatedData(false, inputsCopy);
+
+ {
+ QMutexLocker k(&_imp->pluginsPropMutex);
+ _imp->mustComputeInputRelatedData = false;
+ }
+
+ return hasChanged;
+}
+
+bool
+Node::isInputRelatedDataDirty() const
+{
+ QMutexLocker k(&_imp->pluginsPropMutex);
+ return _imp->mustComputeInputRelatedData;
+}
+
+void
+Node::forceRefreshAllInputRelatedData()
+{
+ markInputRelatedDataDirtyRecursive();
+ refreshInputRelatedDataRecursive();
+}
+
+void
+Node::markInputRelatedDataDirtyRecursiveInternal(std::list& markedNodes) {
+ std::list::iterator found = std::find(markedNodes.begin(), markedNodes.end(), this);
+ if (found != markedNodes.end()) {
+ return;
+ }
+ {
+ QMutexLocker k(&_imp->pluginsPropMutex);
+ _imp->mustComputeInputRelatedData = true;
+ }
+ markedNodes.push_back(this);
+
+ std::list outputs;
+ getOutputsWithGroupRedirection(outputs);
+ for (std::list::const_iterator it = outputs.begin(); it != outputs.end(); ++it) {
+ (*it)->markInputRelatedDataDirtyRecursiveInternal( markedNodes );
+ }
+
+
+
+}
+
+void
+Node::markInputRelatedDataDirtyRecursive()
+{
+ std::list marked;
+ markInputRelatedDataDirtyRecursiveInternal(marked);
+}
+
+
+void
+Node::refreshInputRelatedDataRecursive()
+{
+ std::list markedNodes;
+ if (refreshInputRelatedDataInternal(markedNodes)) {
+
+ ///Now notify outputs we have changed
+ std::list outputs;
+ getOutputsWithGroupRedirection(outputs);
+ for (std::list::const_iterator it = outputs.begin(); it != outputs.end(); ++it) {
+ (*it)->refreshInputRelatedDataInternal( markedNodes );
+ }
+ }
+}
+
+bool
+Node::isDraftModeUsed() const
+{
+ QMutexLocker k(&_imp->pluginsPropMutex);
+ return _imp->draftModeUsed;
+}
+
void
Node::setPosition(double x,double y)
{
@@ -6599,59 +6872,6 @@ Node::isSettingsPanelOpened() const
}
-void
-Node::restoreClipPreferencesRecursive(std::list& markedNodes)
-{
- std::list::const_iterator found = std::find(markedNodes.begin(), markedNodes.end(), this);
- if (found != markedNodes.end()) {
- return;
- }
-
- /*
- * Always call getClipPreferences on the inputs first since the preference of this node may
- * depend on the inputs.
- */
- boost::shared_ptr roto = getRotoContext();
- NodePtr rotoNode;
- if (roto) {
- rotoNode = roto->getNode();
- }
- boost::shared_ptr rotoItem = getAttachedRotoItem();
-
- for (int i = 0; i < getMaxInputCount(); ++i) {
- NodePtr input = getInput(i);
- if (input) {
- if (rotoItem) {
- if (rotoItem->getContext()->getNode() == input) {
- continue;
- }
- }
- input->restoreClipPreferencesRecursive(markedNodes);
- }
- }
-
- if (roto) {
- NodeList nodes;
- roto->getRotoPaintTreeNodes(&nodes);
- for (NodeList::iterator it = nodes.begin(); it!=nodes.end(); ++it) {
- (*it)->restoreClipPreferencesRecursive(markedNodes);
- }
- }
-
- /*
- * And now call getClipPreferences on ourselves
- */
-
- //Nb: we clear the action cache because when creating the node many calls to getRoD and stuff might have returned
- //empty rectangles, but since we force the hash to remain what was in the project file, we might then get wrong RoDs returned
- _imp->liveInstance->clearActionsCache();
-
- _imp->liveInstance->restoreClipPreferences();
- refreshChannelSelectors(false);
-
- markedNodes.push_back(this);
-
-}
void
@@ -7162,16 +7382,17 @@ Node::getChannelSelectorKnob(int inputNb) const
return found->second.layer.lock();
}
-void
+bool
Node::refreshChannelSelectors(bool setValues)
{
if (!isNodeCreated()) {
- return;
+ return false;
}
_imp->liveInstance->setComponentsAvailableDirty(true);
int time = getApp()->getTimeLine()->currentFrame();
+ bool hasChanged = false;
for (std::map::iterator it = _imp->channelsSelectors.begin(); it != _imp->channelsSelectors.end(); ++it) {
NodePtr node;
@@ -7182,9 +7403,8 @@ Node::refreshChannelSelectors(bool setValues)
}
boost::shared_ptr layerKnob = it->second.layer.lock();
- std::vector currentLayerEntries = layerKnob->getEntries_mt_safe();
-
- std::string curLayer = it->second.layerName.lock()->getValue();
+ const std::vector currentLayerEntries = layerKnob->getEntries_mt_safe();
+ const std::string curLayer = it->second.layerName.lock()->getValue();
std::vector choices;
@@ -7242,13 +7462,14 @@ Node::refreshChannelSelectors(bool setValues)
}
}
}
- }
+ } // if (node) {
if (!gotColor) {
assert(choices.size() > 0);
std::vector::iterator pos = choices.begin();
++pos;
colorIndex = 1;
+ colorComp = ImageComponents::getRGBAComponents();
choices.insert(pos,kNatronRGBAComponentsName);
}
@@ -7264,9 +7485,20 @@ Node::refreshChannelSelectors(bool setValues)
if (!gotMotionBw) {
choices.push_back(kNatronBackwardMotionVectorsPlaneName);
}
-
+
+ if (choices.size() != currentLayerEntries.size()) {
+ hasChanged = true;
+ } else {
+ for (std::size_t i = 0; i < currentLayerEntries.size(); ++i) {
+ if (currentLayerEntries[i] != choices[i]) {
+ hasChanged = true;
+ break;
+ }
+ }
+ }
layerKnob->populateChoices(choices);
+
if (setValues) {
assert(colorIndex != -1 && colorIndex >= 0 && colorIndex < (int)choices.size());
@@ -7290,7 +7522,7 @@ Node::refreshChannelSelectors(bool setValues)
layerKnob->setValue(i, 0);
_imp->liveInstance->endChanges(true);
layerKnob->unblockValueChanges();
- if (isColor && _imp->enabledChan[0].lock()) {
+ if (isColor && it->first == -1 && _imp->enabledChan[0].lock()) {
assert(colorIndex != -1);
//Since color plane may have changed (RGB, or RGBA or Alpha), adjust the secretness of the checkboxes
const std::vector& channels = colorComp.getComponentsNames();
@@ -7306,8 +7538,8 @@ Node::refreshChannelSelectors(bool setValues)
}
}
}
- }
- }
+ } // if (setValues) {
+ } // for (std::map::iterator it = _imp->channelsSelectors.begin(); it != _imp->channelsSelectors.end(); ++it) {
for (std::map::iterator it = _imp->maskSelectors.begin(); it != _imp->maskSelectors.end(); ++it) {
NodePtr node;
@@ -7317,9 +7549,8 @@ Node::refreshChannelSelectors(bool setValues)
node = getInput(it->first);
}
- std::vector currentLayerEntries = it->second.channel.lock()->getEntries_mt_safe();
-
- std::string curLayer = it->second.channelName.lock()->getValue();
+ const std::vector currentLayerEntries = it->second.channel.lock()->getEntries_mt_safe();
+ const std::string curLayer = it->second.channelName.lock()->getValue();
std::vector choices;
@@ -7378,8 +7609,20 @@ Node::refreshChannelSelectors(bool setValues)
}
alphaIndex = choices.size() - 1;
}
+
+ if (choices.size() != currentLayerEntries.size()) {
+ hasChanged = true;
+ } else {
+ for (std::size_t i = 0; i < currentLayerEntries.size(); ++i) {
+ if (currentLayerEntries[i] != choices[i]) {
+ hasChanged = true;
+ break;
+ }
+ }
+ }
it->second.channel.lock()->populateChoices(choices);
+
if (setValues) {
assert(alphaIndex != -1 && alphaIndex >= 0 && alphaIndex < (int)choices.size());
it->second.channel.lock()->setValue(alphaIndex,0);
@@ -7403,6 +7646,8 @@ Node::refreshChannelSelectors(bool setValues)
//Notify the effect channels have changed (the viewer needs this)
_imp->liveInstance->onChannelsSelectorRefreshed();
+ return hasChanged;
+
} // Node::refreshChannelSelectors(bool setValues)
bool
diff --git a/Engine/Node.h b/Engine/Node.h
index f4a5bd7b8c..16c627013e 100644
--- a/Engine/Node.h
+++ b/Engine/Node.h
@@ -916,7 +916,6 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
bool isForceCachingEnabled() const;
- void restoreClipPreferencesRecursive(std::list& markedNodes);
/**
* @brief Declares to Python all parameters as attribute of the variable representing this node.
@@ -1009,7 +1008,8 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
unsigned int getPluginPythonModuleVersion() const;
- void refreshChannelSelectors(bool setValues);
+ //Returns true if changed
+ bool refreshChannelSelectors(bool setValues);
bool getProcessChannel(int channelIndex) const;
@@ -1030,8 +1030,31 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
void removeAllImagesFromCacheWithMatchingIDAndDifferentKey(U64 nodeHashKey);
void removeAllImagesFromCache();
+ bool isDraftModeUsed() const;
+ bool isInputRelatedDataDirty() const;
+
+ void forceRefreshAllInputRelatedData();
+
private:
+ void refreshInputRelatedDataRecursive();
+
+ void refreshAllInputRelatedData(bool canChangeValues);
+
+ bool refreshMaskEnabledNess(int inpubNb);
+
+ bool refreshLayersChoiceSecretness(int inpubNb);
+
+ void markInputRelatedDataDirtyRecursive();
+
+ void markInputRelatedDataDirtyRecursiveInternal(std::list& markedNodes);
+
+ bool refreshAllInputRelatedData(bool hasSerializationData,const std::vector >& inputs);
+
+ bool refreshInputRelatedDataInternal(std::list& markedNodes);
+
+ bool refreshDraftFlagInternal(const std::vector >& inputs);
+
void setNameInternal(const std::string& name);
public Q_SLOTS:
diff --git a/Engine/NodeGroup.cpp b/Engine/NodeGroup.cpp
index 5d137cdb7f..3e6226c1e8 100644
--- a/Engine/NodeGroup.cpp
+++ b/Engine/NodeGroup.cpp
@@ -913,7 +913,7 @@ NodeCollection::recomputeFrameRangeForAllReaders(int* firstFrame,int* lastFrame)
}
void
-NodeCollection::forceGetClipPreferencesOnAllTrees()
+NodeCollection::forceComputeInputDependentDataOnAllTrees()
{
NodeList nodes;
getNodes_recursive(nodes);
@@ -922,7 +922,7 @@ NodeCollection::forceGetClipPreferencesOnAllTrees()
std::list markedNodes;
for (std::list::iterator it = trees.begin(); it != trees.end(); ++it) {
- it->output.node->restoreClipPreferencesRecursive(markedNodes);
+ it->output.node->forceRefreshAllInputRelatedData();
}
}
diff --git a/Engine/NodeGroup.h b/Engine/NodeGroup.h
index d565d27baa..6883872b01 100644
--- a/Engine/NodeGroup.h
+++ b/Engine/NodeGroup.h
@@ -267,7 +267,7 @@ class NodeCollection
void getParallelRenderArgs(std::map,ParallelRenderArgs >& argsMap) const;
- void forceGetClipPreferencesOnAllTrees();
+ void forceComputeInputDependentDataOnAllTrees();
/**
* @brief Callback called when a node of the collection is being deactivated
diff --git a/Engine/OfxEffectInstance.cpp b/Engine/OfxEffectInstance.cpp
index d9847bf455..389d6bf387 100644
--- a/Engine/OfxEffectInstance.cpp
+++ b/Engine/OfxEffectInstance.cpp
@@ -218,7 +218,8 @@ OfxEffectInstance::createOfxImageEffectInstance(OFX::Host::ImageEffect::ImageEff
const NodeSerialization* serialization,
const std::list >& paramValues,
bool allowFileDialogs,
- bool disableRenderScaleSupport)
+ bool disableRenderScaleSupport,
+ bool *hasUsedFileDialog)
{
/*Replicate of the code in OFX::Host::ImageEffect::ImageEffectPlugin::createInstance.
We need to pass more parameters to the constructor . That means we cannot
@@ -233,6 +234,9 @@ OfxEffectInstance::createOfxImageEffectInstance(OFX::Host::ImageEffect::ImageEff
assert( QThread::currentThread() == qApp->thread() );
assert(plugin && desc && context != eContextNone);
+
+ *hasUsedFileDialog = false;
+
_context = context;
@@ -326,6 +330,7 @@ OfxEffectInstance::createOfxImageEffectInstance(OFX::Host::ImageEffect::ImageEff
images = getApp()->saveImageFileDialog();
}
if (!images.empty()) {
+ *hasUsedFileDialog = true;
boost::shared_ptr defaultFile = createDefaultValueForParam(kOfxImageEffectFileParamName, images);
CreateNodeArgs::DefaultValuesList list;
list.push_back(defaultFile);
@@ -391,19 +396,9 @@ OfxEffectInstance::createOfxImageEffectInstance(OFX::Host::ImageEffect::ImageEff
// If we don't, the following assert will crash at the beginning of EffectInstance::renderRoIInternal():
// assert(isSupportedBitDepth(outputDepth) && isSupportedComponent(-1, outputComponents));
// If a component/bitdepth is not supported (this is probably a plugin bug), use the closest one, but don't crash Natron.
- checkOFXClipPreferences_public(getApp()->getTimeLine()->currentFrame(), scaleOne, kOfxChangeUserEdited,true, false);
-
-
- // check that the plugin supports kOfxImageComponentRGBA for all the clips
- /*const std::vector & clips = effectInstance()->getDescriptor().getClipsByOrder();
- for (U32 i = 0; i < clips.size(); ++i) {
- if ( (clips[i]->getProps().findStringPropValueIndex(kOfxImageEffectPropSupportedComponents, kOfxImageComponentRGBA) == -1)
- && !clips[i]->isOptional() && !clips[i]->isMask() ) {
- appPTR->writeToOfxLog_mt_safe( QString( plugin->getDescriptor().getLabel().c_str() )
- + "RGBA components not supported by OFX plugin in context " + QString( context.c_str() ) );
- throw std::runtime_error(std::string("RGBA components not supported by OFX plugin in context ") + context);
- }
- }*/
+ //checkOFXClipPreferences_public(getApp()->getTimeLine()->currentFrame(), scaleOne, kOfxChangeUserEdited,true, false);
+
+
} catch (const std::exception & e) {
qDebug() << "Error: Caught exception while creating OfxImageEffectInstance" << ": " << e.what();
throw;
@@ -414,25 +409,7 @@ OfxEffectInstance::createOfxImageEffectInstance(OFX::Host::ImageEffect::ImageEff
_initialized = true;
- ///Now that the instance is created, make sure instanceChangedActino is called for all extra default values
- ///that we set
- for (std::list >::const_iterator it = paramValues.begin(); it != paramValues.end(); ++it) {
- boost::shared_ptr knob = getKnobByName((*it)->getName());
- if (knob) {
- for (int i = 0; i < knob->getDimension(); ++i) {
- knob->evaluateValueChange(i, Natron::eValueChangedReasonUserEdited);
- }
- } else {
- qDebug() << "WARNING: No such parameter " << (*it)->getName().c_str();
- }
- }
-
- if (!images.empty()) {
- boost::shared_ptr fileNameKnob = getKnobByName(kOfxImageEffectFileParamName);
- if (fileNameKnob) {
- fileNameKnob->evaluateValueChange(0,Natron::eValueChangedReasonUserEdited);
- }
- }
+
endChanges();
} // createOfxImageEffectInstance
@@ -944,9 +921,7 @@ void
OfxEffectInstance::onInputChanged(int inputNo)
{
- if (getApp()->getProject()->isLoadingProject() || getApp()->isCreatingPythonGroup()) {
- return;
- }
+
assert(_context != eContextNone);
OfxClipInstance* clip = getClipCorrespondingToInput(inputNo);
assert(clip);
@@ -955,56 +930,8 @@ OfxEffectInstance::onInputChanged(int inputNo)
s.x = s.y = 1.;
- /**
- * The plug-in might call getImage, set a valid thread storage on the tree.
- **/
- ParallelRenderArgsSetter frameRenderArgs(getApp()->getProject().get(),
- time,
- 0 /*view*/,
- true,
- false,
- false,
- 0,
- getNode(),
- 0,
- 0, //texture index
- getApp()->getTimeLine().get(),
- NodePtr(),
- false,
- false,
- false,
- boost::shared_ptr());
-
EffectPointerThreadProperty_RAII propHolder_raii(this);
-
- ///Don't do clip preferences while loading a project, they will be refreshed globally once the project is loaded.
-
- ///if all non optional clips are connected, call getClipPrefs
- ///The clip preferences action is never called until all non optional clips have been attached to the plugin.
- if (_effect->areAllNonOptionalClipsConnected()) {
-
- ///Render scale support might not have been set already because getRegionOfDefinition could have failed until all non optional inputs were connected
- if (supportsRenderScaleMaybe() == eSupportsMaybe) {
- OfxRectD rod;
- OfxPointD scaleOne;
- scaleOne.x = scaleOne.y = 1.;
- OfxStatus rodstat = _effect->getRegionOfDefinitionAction(time, scaleOne, 0, rod);
- if ( (rodstat == kOfxStatOK) || (rodstat == kOfxStatReplyDefault) ) {
- OfxPointD scale;
- scale.x = 0.5;
- scale.y = 0.5;
- rodstat = _effect->getRegionOfDefinitionAction(time, scale, 0, rod);
- if ( (rodstat == kOfxStatOK) || (rodstat == kOfxStatReplyDefault) ) {
- setSupportsRenderScaleMaybe(eSupportsYes);
- } else {
- setSupportsRenderScaleMaybe(eSupportsNo);
- }
- }
-
- }
- checkOFXClipPreferences_public(time,s,kOfxChangeUserEdited,true, true);
- }
-
+
{
RECURSIVE_ACTION();
SET_CAN_SET_VALUE(true);
@@ -1020,7 +947,6 @@ OfxEffectInstance::onInputChanged(int inputNo)
_effect->endInstanceChangedAction(kOfxChangeUserEdited);
}
- getNode()->refreshDynamicProperties();
}
/** @brief map a std::string to a context */
@@ -1286,7 +1212,7 @@ clipPrefsProxy(OfxEffectInstance* self,
-void
+bool
OfxEffectInstance::checkOFXClipPreferences(double time,
const RenderScale & scale,
const std::string & reason,
@@ -1294,7 +1220,7 @@ OfxEffectInstance::checkOFXClipPreferences(double time,
{
if (!_created) {
- return;
+ return false;
}
assert(_context != eContextNone);
assert( QThread::currentThread() == qApp->thread() );
@@ -1312,15 +1238,15 @@ OfxEffectInstance::checkOFXClipPreferences(double time,
QWriteLocker preferencesLocker(_preferencesLock);
if (forceGetClipPrefAction) {
if (!_effect->getClipPreferences_safe(clipsPrefs,effectPrefs)) {
- return;
+ return false;
}
} else {
if (_effect->areClipPrefsDirty()) {
if (!_effect->getClipPreferences_safe(clipsPrefs, effectPrefs)) {
- return;
+ return false;
}
} else {
- return;
+ return false;
}
}
}
@@ -1333,6 +1259,7 @@ OfxEffectInstance::checkOFXClipPreferences(double time,
clipPrefsProxy(this,time,clipsPrefs,effectPrefs,modifiedClips);
+ bool changed = false;
////////////////////////////////////////////////////////////////
////////////////////////////////
@@ -1341,12 +1268,21 @@ OfxEffectInstance::checkOFXClipPreferences(double time,
{
QWriteLocker l(_preferencesLock);
for (std::map::const_iterator it = clipsPrefs.begin(); it != clipsPrefs.end(); ++it) {
- it->first->setComponents(it->second.components);
- it->first->setPixelDepth(it->second.bitdepth);
- it->first->setAspectRatio(it->second.par);
+ if (it->first->getComponents() != it->second.components) {
+ it->first->setComponents(it->second.components);
+ changed = true;
+ }
+ if (it->second.bitdepth != it->first->getPixelDepth()) {
+ it->first->setPixelDepth(it->second.bitdepth);
+ changed = true;
+ }
+ if (it->second.par != it->first->getAspectRatio()) {
+ it->first->setAspectRatio(it->second.par);
+ changed = true;
+ }
}
- effectInstance()->updatePreferences_safe(effectPrefs.frameRate, effectPrefs.fielding, effectPrefs.premult,
+ changed |= effectInstance()->updatePreferences_safe(effectPrefs.frameRate, effectPrefs.fielding, effectPrefs.premult,
effectPrefs.continuous, effectPrefs.frameVarying);
}
@@ -1368,45 +1304,9 @@ OfxEffectInstance::checkOFXClipPreferences(double time,
}
}
-
+ return changed;
} // checkOFXClipPreferences
-void
-OfxEffectInstance::restoreClipPreferences()
-{
- assert(_context != eContextNone);
-
- double time = getApp()->getTimeLine()->currentFrame();
- RenderScale s;
- s.x = s.y = 1.;
-
- ///Render scale support might not have been set already because getRegionOfDefinition could have failed until all non optional inputs were connected
- if (supportsRenderScaleMaybe() == eSupportsMaybe) {
- OfxRectD rod;
- OfxPointD scaleOne;
- scaleOne.x = scaleOne.y = 1.;
- OfxStatus rodstat = _effect->getRegionOfDefinitionAction(time, scaleOne, 0, rod);
- if ( (rodstat == kOfxStatOK) || (rodstat == kOfxStatReplyDefault) ) {
- OfxPointD scale;
- scale.x = 0.5;
- scale.y = 0.5;
- rodstat = _effect->getRegionOfDefinitionAction(time, scale, 0, rod);
- if ( (rodstat == kOfxStatOK) || (rodstat == kOfxStatReplyDefault) ) {
- setSupportsRenderScaleMaybe(eSupportsYes);
- } else {
- setSupportsRenderScaleMaybe(eSupportsNo);
- }
- }
-
- }
-
-
- ///if all non optional clips are connected, call getClipPrefs
- ///The clip preferences action is never called until all non optional clips have been attached to the plugin.
- if ( _effect->areAllNonOptionalClipsConnected() ) {
- checkOFXClipPreferences_public(time,s,kOfxChangeUserEdited,true, false);
- }
-}
std::vector
OfxEffectInstance::supportedFileFormats() const
diff --git a/Engine/OfxEffectInstance.h b/Engine/OfxEffectInstance.h
index ecb21477bc..e4f3c36530 100644
--- a/Engine/OfxEffectInstance.h
+++ b/Engine/OfxEffectInstance.h
@@ -85,7 +85,8 @@ class AbstractOfxEffectInstance
const NodeSerialization* serialization,
const std::list >& paramValues,
bool allowFileDialogs,
- bool disableRenderScaleSupport) = 0;
+ bool disableRenderScaleSupport,
+ bool *hasUsedFileDialog) = 0;
static QStringList makePluginGrouping(const std::string & pluginIdentifier,
int versionMajor, int versionMinor,
const std::string & pluginLabel,
@@ -114,7 +115,8 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
const NodeSerialization* serialization,
const std::list >& paramValues,
bool allowFileDialogs,
- bool disableRenderScaleSupport) OVERRIDE FINAL;
+ bool disableRenderScaleSupport,
+ bool *hasUsedFileDialog) OVERRIDE FINAL;
Natron::OfxImageEffectInstance* effectInstance() WARN_UNUSED_RETURN
{
@@ -246,7 +248,6 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
virtual bool supportsMultipleClipsPAR() const OVERRIDE FINAL WARN_UNUSED_RETURN;
virtual bool isHostChannelSelectorSupported(bool* defaultR,bool* defaultG, bool* defaultB, bool* defaultA) const OVERRIDE FINAL WARN_UNUSED_RETURN;
virtual void onInputChanged(int inputNo) OVERRIDE FINAL;
- virtual void restoreClipPreferences() OVERRIDE FINAL;
virtual std::vector supportedFileFormats() const OVERRIDE FINAL;
virtual Natron::StatusEnum beginSequenceRender(double first,
double last,
@@ -271,7 +272,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
virtual void getPreferredDepthAndComponents(int inputNb, std::list* comp, Natron::ImageBitDepthEnum* depth) const OVERRIDE FINAL;
virtual Natron::SequentialPreferenceEnum getSequentialPreference() const OVERRIDE FINAL WARN_UNUSED_RETURN;
virtual Natron::ImagePremultiplicationEnum getOutputPremultiplication() const OVERRIDE FINAL WARN_UNUSED_RETURN;
- virtual void checkOFXClipPreferences(double time,
+ virtual bool checkOFXClipPreferences(double time,
const RenderScale & scale,
const std::string & reason,
bool forceGetClipPrefAction) OVERRIDE FINAL;
diff --git a/Engine/OfxHost.cpp b/Engine/OfxHost.cpp
index 9cccbe134e..749c3e987b 100644
--- a/Engine/OfxHost.cpp
+++ b/Engine/OfxHost.cpp
@@ -512,7 +512,8 @@ Natron::OfxHost::createOfxEffect(boost::shared_ptr node,
const NodeSerialization* serialization,
const std::list >& paramValues,
bool allowFileDialogs,
- bool disableRenderScaleSupport)
+ bool disableRenderScaleSupport,
+ bool *hasUsedFileDialog)
{
assert(node);
const Natron::Plugin* natronPlugin = node->getPlugin();
@@ -528,7 +529,7 @@ Natron::OfxHost::createOfxEffect(boost::shared_ptr node,
node->setLiveInstance(hostSideEffect);
}
- hostSideEffect->createOfxImageEffectInstance(plugin, desc, ctx,serialization,paramValues,allowFileDialogs,disableRenderScaleSupport);
+ hostSideEffect->createOfxImageEffectInstance(plugin, desc, ctx,serialization,paramValues,allowFileDialogs,disableRenderScaleSupport,hasUsedFileDialog);
return hostSideEffect;
}
diff --git a/Engine/OfxHost.h b/Engine/OfxHost.h
index ae31615067..74046538f6 100644
--- a/Engine/OfxHost.h
+++ b/Engine/OfxHost.h
@@ -142,7 +142,8 @@ class OfxHost
const NodeSerialization* serialization,
const std::list >& paramValues,
bool allowFileDialogs,
- bool disableRenderScaleSupport);
+ bool disableRenderScaleSupport,
+ bool *hasUsedFileDialog);
void addPathToLoadOFXPlugins(const std::string path);
diff --git a/Engine/OfxImageEffectInstance.cpp b/Engine/OfxImageEffectInstance.cpp
index 6a50d2a449..3fd6fb85d2 100644
--- a/Engine/OfxImageEffectInstance.cpp
+++ b/Engine/OfxImageEffectInstance.cpp
@@ -1061,15 +1061,32 @@ OfxImageEffectInstance::getClipPreferences_safe(std::mapgetLiveInstance();
assert(effect);
+ if (effect->supportsRenderScaleMaybe() == Natron::EffectInstance::eSupportsMaybe) {
+ /*
+ If this flag was not set already that means it probably failed all calls to getRegionOfDefinition.
+ We safely fail here
+ */
+ return eStatusFailed;
+ }
assert(effect->supportsRenderScaleMaybe() == Natron::EffectInstance::eSupportsNo ||
effect->supportsRenderScaleMaybe() == Natron::EffectInstance::eSupportsYes);
bool supportsRs = effect->supportsRenderScale();
diff --git a/Engine/Project.cpp b/Engine/Project.cpp
index b1700653d9..9f07eb2261 100644
--- a/Engine/Project.cpp
+++ b/Engine/Project.cpp
@@ -1234,7 +1234,7 @@ Project::onKnobValueChanged(KnobI* knob,
}
///Format change, hence probably the PAR so run getClipPreferences again
- forceGetClipPreferencesOnAllTrees();
+ forceComputeInputDependentDataOnAllTrees();
}
Q_EMIT formatChanged(frmt);
}
@@ -1243,7 +1243,7 @@ Project::onKnobValueChanged(KnobI* knob,
} else if ( knob == _imp->previewMode.get() ) {
Q_EMIT autoPreviewChanged( _imp->previewMode->getValue() );
} else if ( knob == _imp->frameRate.get() ) {
- forceGetClipPreferencesOnAllTrees();
+ forceComputeInputDependentDataOnAllTrees();
} else if (knob == _imp->frameRange.get()) {
int first = _imp->frameRange->getValue(0);
int last = _imp->frameRange->getValue(1);
diff --git a/Engine/ProjectPrivate.cpp b/Engine/ProjectPrivate.cpp
index 05691cf0d8..46a6a9cf3e 100644
--- a/Engine/ProjectPrivate.cpp
+++ b/Engine/ProjectPrivate.cpp
@@ -198,7 +198,7 @@ ProjectPrivate::restoreFromSerialization(const ProjectSerialization & obj,
- _publicInterface->forceGetClipPreferencesOnAllTrees();
+ _publicInterface->forceComputeInputDependentDataOnAllTrees();
QDateTime time = QDateTime::currentDateTime();
autoSetProjectFormat = false;
diff --git a/Engine/ViewerInstance.cpp b/Engine/ViewerInstance.cpp
index 7e0b5718cd..5c6ef46247 100644
--- a/Engine/ViewerInstance.cpp
+++ b/Engine/ViewerInstance.cpp
@@ -2748,17 +2748,17 @@ ViewerInstance::isInputChangeRequestedFromViewer() const
}
void
-ViewerInstance::onInputChanged(int inputNb)
+ViewerInstance::refreshActiveInputs(int inputNbChanged)
{
assert( QThread::currentThread() == qApp->thread() );
- NodePtr inputNode = getNode()->getRealInput(inputNb);
+ NodePtr inputNode = getNode()->getRealInput(inputNbChanged);
{
QMutexLocker l(&_imp->activeInputsMutex);
if (!inputNode) {
///check if the input was one of the active ones if so set to -1
- if (_imp->activeInputs[0] == inputNb) {
+ if (_imp->activeInputs[0] == inputNbChanged) {
_imp->activeInputs[0] = -1;
- } else if (_imp->activeInputs[1] == inputNb) {
+ } else if (_imp->activeInputs[1] == inputNbChanged) {
_imp->activeInputs[1] = -1;
}
} else {
@@ -2768,31 +2768,32 @@ ViewerInstance::onInputChanged(int inputNb)
_imp->uiContext->setCompositingOperator(Natron::eViewerCompositingOperatorWipe);
op = Natron::eViewerCompositingOperatorWipe;
}
- _imp->activeInputs[1] = inputNb;
+ _imp->activeInputs[1] = inputNbChanged;
} else {
- _imp->activeInputs[0] = inputNb;
+ _imp->activeInputs[0] = inputNbChanged;
}
}
}
Q_EMIT activeInputsChanged();
Q_EMIT refreshOptionalState();
- Q_EMIT clipPreferencesChanged();
}
void
-ViewerInstance::restoreClipPreferences()
+ViewerInstance::onInputChanged(int /*inputNb*/)
{
+
Q_EMIT clipPreferencesChanged();
}
-void
+bool
ViewerInstance::checkOFXClipPreferences(double /*time*/,
const RenderScale & /*scale*/,
const std::string & /*reason*/,
bool /*forceGetClipPrefAction*/)
{
Q_EMIT clipPreferencesChanged();
+ return false;
}
void
diff --git a/Engine/ViewerInstance.h b/Engine/ViewerInstance.h
index 1dd06405aa..867f8c3545 100644
--- a/Engine/ViewerInstance.h
+++ b/Engine/ViewerInstance.h
@@ -213,8 +213,8 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
virtual void onInputChanged(int inputNb) OVERRIDE FINAL;
- virtual void restoreClipPreferences() OVERRIDE FINAL;
-
+ void refreshActiveInputs(int inputNbChanged);
+
void setInputA(int inputNb);
void setInputB(int inputNb);
@@ -233,7 +233,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
static const Natron::Color::Lut* lutFromColorspace(Natron::ViewerColorSpaceEnum cs) WARN_UNUSED_RETURN;
- virtual void checkOFXClipPreferences(double time,
+ virtual bool checkOFXClipPreferences(double time,
const RenderScale & scale,
const std::string & reason,
bool forceGetClipPrefAction) OVERRIDE FINAL;
diff --git a/Gui/Gui.cpp b/Gui/Gui.cpp
index c4186922b9..ace60d9162 100644
--- a/Gui/Gui.cpp
+++ b/Gui/Gui.cpp
@@ -235,10 +235,7 @@ Gui::closeEvent(QCloseEvent* e)
boost::shared_ptr
Gui::createNodeGUI( boost::shared_ptr node,
bool requestedByLoad,
- double xPosHint,
- double yPosHint,
- bool pushUndoRedoCommand,
- bool autoConnect)
+ bool pushUndoRedoCommand)
{
assert(_imp->_nodeGraphArea);
@@ -252,8 +249,7 @@ Gui::createNodeGUI( boost::shared_ptr node,
} else {
graph = _imp->_nodeGraphArea;
}
- boost::shared_ptr nodeGui = graph->createNodeGUI(node, requestedByLoad,
- xPosHint, yPosHint, pushUndoRedoCommand, autoConnect);
+ boost::shared_ptr nodeGui = graph->createNodeGUI(node, requestedByLoad,pushUndoRedoCommand);
QObject::connect( node.get(), SIGNAL( labelChanged(QString) ), this, SLOT( onNodeNameChanged(QString) ) );
assert(nodeGui);
diff --git a/Gui/Gui.h b/Gui/Gui.h
index c8ce7aeb79..4957891ca6 100644
--- a/Gui/Gui.h
+++ b/Gui/Gui.h
@@ -140,10 +140,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
boost::shared_ptr createNodeGUI(boost::shared_ptr node,
bool requestedByLoad,
- double xPosHint,
- double yPosHint,
- bool pushUndoRedoCommand,
- bool autoConnect);
+ bool pushUndoRedoCommand);
void addNodeGuiToCurveEditor(const boost::shared_ptr &node);
diff --git a/Gui/GuiAppInstance.cpp b/Gui/GuiAppInstance.cpp
index 41f59917da..66961868ba 100644
--- a/Gui/GuiAppInstance.cpp
+++ b/Gui/GuiAppInstance.cpp
@@ -45,6 +45,7 @@
#include "Gui/GuiApplicationManager.h"
#include "Gui/Gui.h"
+#include "Gui/BackdropGui.h"
#include "Gui/NodeGraph.h"
#include "Gui/NodeGui.h"
#include "Gui/MultiInstancePanel.h"
@@ -421,7 +422,7 @@ GuiAppInstance::createNodeGui(const boost::shared_ptr &node,
std::list > selectedNodes = graph->getSelectedNodes();
- boost::shared_ptr nodegui = _imp->_gui->createNodeGUI(node,loadRequest,xPosHint,yPosHint,pushUndoRedoCommand,autoConnect);
+ boost::shared_ptr nodegui = _imp->_gui->createNodeGUI(node,loadRequest,pushUndoRedoCommand);
assert(nodegui);
if ( parentMultiInstance && nodegui) {
@@ -464,6 +465,32 @@ GuiAppInstance::createNodeGui(const boost::shared_ptr &node,
triggerAutoSave();
}
+
+
+ ///only move main instances
+ if (node->getParentMultiInstanceName().empty()) {
+ if (selectedNodes.empty()) {
+ autoConnect = false;
+ }
+ if ( (xPosHint != INT_MIN) && (yPosHint != INT_MIN) && !autoConnect ) {
+ QPointF pos = nodegui->mapToParent( nodegui->mapFromScene( QPointF(xPosHint,yPosHint) ) );
+ nodegui->refreshPosition( pos.x(),pos.y(), true );
+ } else {
+ BackDropGui* isBd = dynamic_cast(nodegui.get());
+ if (!isBd && !isGroup) {
+ boost::shared_ptr selectedNode;
+ if (selectedNodes.size() == 1) {
+ selectedNode = selectedNodes.front();
+ BackDropGui* isBackdropGui = dynamic_cast(selectedNode.get());
+ if (isBackdropGui) {
+ selectedNode.reset();
+ }
+ }
+ nodegui->getDagGui()->moveNodesForIdealPosition(nodegui,selectedNode,autoConnect);
+ }
+ }
+ }
+
} // createNodeGui
std::string
@@ -1061,11 +1088,18 @@ GuiAppInstance::onGroupCreationFinished(const boost::shared_ptr& n
graph = _imp->_gui->getNodeGraph();
}
assert(graph);
-
+ std::list > selectedNodes = graph->getSelectedNodes();
+ boost::shared_ptr selectedNode;
+ if (!selectedNodes.empty()) {
+ selectedNode = selectedNodes.front();
+ if (dynamic_cast(selectedNode.get())) {
+ selectedNode.reset();
+ }
+ }
boost::shared_ptr node_gui_i = node->getNodeGui();
assert(node_gui_i);
boost::shared_ptr nodeGui = boost::dynamic_pointer_cast(node_gui_i);
- graph->moveNodesForIdealPosition(nodeGui, true);
+ graph->moveNodesForIdealPosition(nodeGui, selectedNode, true);
std::list viewers;
node->hasViewersConnected(&viewers);
diff --git a/Gui/NodeGraph.cpp b/Gui/NodeGraph.cpp
index ad14971c49..979bf51161 100644
--- a/Gui/NodeGraph.cpp
+++ b/Gui/NodeGraph.cpp
@@ -329,10 +329,7 @@ NodeGraph::visibleWidgetRect() const
boost::shared_ptr
NodeGraph::createNodeGUI(const boost::shared_ptr & node,
bool requestedByLoad,
- double xPosHint,
- double yPosHint,
- bool pushUndoRedoCommand,
- bool autoConnect)
+ bool pushUndoRedoCommand)
{
boost::shared_ptr node_ui;
Dot* isDot = dynamic_cast( node->getLiveInstance() );
@@ -382,20 +379,7 @@ NodeGraph::createNodeGUI(const boost::shared_ptr & node,
QMutexLocker l(&_imp->_nodesMutex);
_imp->_nodes.push_back(node_ui);
}
- ///only move main instances
- if ( node->getParentMultiInstanceName().empty() ) {
- if (_imp->_selection.empty()) {
- autoConnect = false;
- }
- if ( (xPosHint != INT_MIN) && (yPosHint != INT_MIN) && !autoConnect ) {
- QPointF pos = node_ui->mapToParent( node_ui->mapFromScene( QPointF(xPosHint,yPosHint) ) );
- node_ui->refreshPosition( pos.x(),pos.y(), true );
- } else {
- if (!isBd && !isGrp) {
- moveNodesForIdealPosition(node_ui,autoConnect);
- }
- }
- }
+
if (!requestedByLoad && (!getGui()->getApp()->isCreatingPythonGroup() || dynamic_cast(node->getLiveInstance()))) {
node_ui->ensurePanelCreated();
diff --git a/Gui/NodeGraph.h b/Gui/NodeGraph.h
index 20e9e35834..615ab02889 100644
--- a/Gui/NodeGraph.h
+++ b/Gui/NodeGraph.h
@@ -83,8 +83,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
boost::shared_ptr getGroup() const;
const std::list< boost::shared_ptr > & getSelectedNodes() const;
- boost::shared_ptr createNodeGUI(const boost::shared_ptr & node,bool requestedByLoad,
- double xPosHint,double yPosHint,bool pushUndoRedoCommand,bool autoConnect);
+ boost::shared_ptr createNodeGUI(const boost::shared_ptr & node,bool requestedByLoad,bool pushUndoRedoCommand);
void selectNode(const boost::shared_ptr & n,bool addToSelection);
@@ -167,7 +166,9 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
* It will move the inputs / outputs slightly to fit this node into the nodegraph
* so they do not overlap.
**/
- void moveNodesForIdealPosition(boost::shared_ptr n,bool autoConnect);
+ void moveNodesForIdealPosition(const boost::shared_ptr &n,
+ const boost::shared_ptr& selected,
+ bool autoConnect);
void copyNodes(const std::list >& nodes,NodeClipBoard& clipboard);
diff --git a/Gui/NodeGraph05.cpp b/Gui/NodeGraph05.cpp
index 13338fc6ea..f083d37bf7 100644
--- a/Gui/NodeGraph05.cpp
+++ b/Gui/NodeGraph05.cpp
@@ -47,7 +47,9 @@ using namespace Natron;
void
-NodeGraph::moveNodesForIdealPosition(boost::shared_ptr node,bool autoConnect)
+NodeGraph::moveNodesForIdealPosition(const boost::shared_ptr &node,
+ const boost::shared_ptr &selected,
+ bool autoConnect)
{
BackDropGui* isBd = dynamic_cast(node.get());
if (isBd) {
@@ -61,15 +63,6 @@ NodeGraph::moveNodesForIdealPosition(boost::shared_ptr node,bool autoCo
/// 1 = pop the node above the selected node and move the inputs of the selected node a little
/// 2 = pop the node below the selected node and move the outputs of the selected node a little
int behavior = 0;
- boost::shared_ptr selected;
-
- if (_imp->_selection.size() == 1) {
- selected = _imp->_selection.front();
- BackDropGui* isBd = dynamic_cast(selected.get());
- if (isBd) {
- selected.reset();
- }
- }
if (!selected || !autoConnect) {
behavior = 0;
From fb5f361bbc2c6ee796b3da0223db294022bb471e Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Mon, 28 Sep 2015 16:40:04 +0200
Subject: [PATCH 017/178] Fix recursion
---
Engine/Engine.pro | 2 +-
Engine/Node.cpp | 46 +++++++++++++++++++++++++++++++---------------
Engine/Node.h | 2 ++
3 files changed, 34 insertions(+), 16 deletions(-)
diff --git a/Engine/Engine.pro b/Engine/Engine.pro
index 197b5db5c9..04fdd8d013 100644
--- a/Engine/Engine.pro
+++ b/Engine/Engine.pro
@@ -72,7 +72,7 @@ win32-msvc* {
# XCode clang 3.5 without optimization generates code that crashes
#(Natron on OSX, XCode 6, Spaceship_Natron.ntp)
*-xcode {
- QMAKE_CXXFLAGS += -O1
+ #QMAKE_CXXFLAGS += -O1
}
SOURCES += \
diff --git a/Engine/Node.cpp b/Engine/Node.cpp
index 4109cd6bae..0e2dc42a21 100644
--- a/Engine/Node.cpp
+++ b/Engine/Node.cpp
@@ -6648,6 +6648,11 @@ Node::refreshAllInputRelatedData(bool canChangeValues,const std::vectorpluginsPropMutex);
+ _imp->mustComputeInputRelatedData = false;
+ }
+
return hasChanged;
}
@@ -6683,11 +6688,6 @@ Node::refreshInputRelatedDataInternal(std::list& markedNodes)
bool hasChanged = refreshAllInputRelatedData(false, inputsCopy);
- {
- QMutexLocker k(&_imp->pluginsPropMutex);
- _imp->mustComputeInputRelatedData = false;
- }
-
return hasChanged;
}
@@ -6702,7 +6702,19 @@ void
Node::forceRefreshAllInputRelatedData()
{
markInputRelatedDataDirtyRecursive();
- refreshInputRelatedDataRecursive();
+
+ NodeGroup* isGroup = dynamic_cast(_imp->liveInstance.get());
+ if (isGroup) {
+ std::list inputs;
+ isGroup->getInputsOutputs(&inputs);
+ for (std::list::iterator it = inputs.begin(); it != inputs.end(); ++it) {
+ if ((*it)) {
+ (*it)->refreshInputRelatedDataRecursive();
+ }
+ }
+ } else {
+ refreshInputRelatedDataRecursive();
+ }
}
void
@@ -6734,20 +6746,24 @@ Node::markInputRelatedDataDirtyRecursive()
markInputRelatedDataDirtyRecursiveInternal(marked);
}
+void
+Node::refreshInputRelatedDataRecursiveInternal(std::list& markedNodes)
+{
+ refreshInputRelatedDataInternal(markedNodes);
+
+ ///Now notify outputs we have changed
+ std::list outputs;
+ getOutputsWithGroupRedirection(outputs);
+ for (std::list::const_iterator it = outputs.begin(); it != outputs.end(); ++it) {
+ (*it)->refreshInputRelatedDataRecursiveInternal( markedNodes );
+ }
+}
void
Node::refreshInputRelatedDataRecursive()
{
std::list markedNodes;
- if (refreshInputRelatedDataInternal(markedNodes)) {
-
- ///Now notify outputs we have changed
- std::list outputs;
- getOutputsWithGroupRedirection(outputs);
- for (std::list::const_iterator it = outputs.begin(); it != outputs.end(); ++it) {
- (*it)->refreshInputRelatedDataInternal( markedNodes );
- }
- }
+ refreshInputRelatedDataRecursiveInternal(markedNodes);
}
bool
diff --git a/Engine/Node.h b/Engine/Node.h
index 16c627013e..f4a85c5a5b 100644
--- a/Engine/Node.h
+++ b/Engine/Node.h
@@ -1037,6 +1037,8 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
private:
+ void refreshInputRelatedDataRecursiveInternal(std::list& markedNodes);
+
void refreshInputRelatedDataRecursive();
void refreshAllInputRelatedData(bool canChangeValues);
From 59a174a01e07cdd9805dd0bc13d76ce5e192639e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Devernay?=
Date: Mon, 28 Sep 2015 17:04:59 +0200
Subject: [PATCH 018/178] travis: fix addons section
---
.travis.yml | 37 +++++++++++++++++++------------------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 0267a6a839..15f782494a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -31,6 +31,8 @@ addons:
# see http://stackoverflow.com/questions/11302758/error-while-copy-constructing-boostshared-ptr-using-c11
# we use the irie/boost ppa for that purpose
- irie-boost
+ # kubuntu-ppa/backports contains OpenCV
+ - kubuntu-ppa-backports
# the PPA xorg-edgers contains cairo 1.12 (required for rotoscoping)
- xorg-edgers-ppa
# ubuntu-toolchain-r/test contains recent versions of gcc
@@ -48,6 +50,23 @@ addons:
- python-pyside
- libpyside-dev
- libshiboken-dev
+ coverity_scan:
+ # customized build script URL
+ # TRAVIS_REPO_SLUG: owner_name/repo_name of repository currently being built
+ # TRAVIS_BRANCH: name of the branch currently being built
+ build_script_url: https://raw.githubusercontent.com/$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH/.travis-coverity-scan-build.sh
+ # project metadata
+ project:
+ name: $TRAVIS_REPO_SLUG
+ # Where email notification of build analysis results will be sent
+ notification_email: frederic.devernay@m4x.org
+ # Commands to prepare for build_command
+ #build_command_prepend: ./configure
+ # This command will be added as an argument to "cov-build" to compile
+ # the project for analysis
+ build_command: "tools/travis/build.sh"
+ # Pattern to match selecting branches that will run analysis
+ branch_pattern: coverity_scan
matrix:
exclude:
@@ -97,21 +116,3 @@ after_success:
after_failure:
- cat install_dependencies.log || true
-addons:
- coverity_scan:
- # customized build script URL
- # TRAVIS_REPO_SLUG: owner_name/repo_name of repository currently being built
- # TRAVIS_BRANCH: name of the branch currently being built
- build_script_url: https://raw.githubusercontent.com/$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH/.travis-coverity-scan-build.sh
- # project metadata
- project:
- name: $TRAVIS_REPO_SLUG
- # Where email notification of build analysis results will be sent
- notification_email: frederic.devernay@m4x.org
- # Commands to prepare for build_command
- #build_command_prepend: ./configure
- # This command will be added as an argument to "cov-build" to compile
- # the project for analysis
- build_command: "tools/travis/build.sh"
- # Pattern to match selecting branches that will run analysis
- branch_pattern: coverity_scan
From 0762d467fa529cf1ad13cd9333517a2aaf7dd5ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Devernay?=
Date: Mon, 28 Sep 2015 17:06:09 +0200
Subject: [PATCH 019/178] update openfx
---
libs/OpenFX | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libs/OpenFX b/libs/OpenFX
index 2b409121b4..5b79aab822 160000
--- a/libs/OpenFX
+++ b/libs/OpenFX
@@ -1 +1 @@
-Subproject commit 2b409121b4ef8e89c92e19dd8a77400c6d4cfd8f
+Subproject commit 5b79aab822b378814e1967236e3576b677ce3b96
From ddcc89eb99d4f4a30b7245f734ab68189ba9790a Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Mon, 28 Sep 2015 17:08:20 +0200
Subject: [PATCH 020/178] Don't call refreshAllInputRelatedData if loading a
project or group
---
Engine/Node.cpp | 4 +++-
Gui/GuiAppInstance.cpp | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/Engine/Node.cpp b/Engine/Node.cpp
index 0e2dc42a21..095d3d1e65 100644
--- a/Engine/Node.cpp
+++ b/Engine/Node.cpp
@@ -724,7 +724,9 @@ Node::load(const std::string & parentMultiInstanceName,
_imp->nodeCreated = true;
- refreshAllInputRelatedData(serialization.isNull());
+ if (!getApp()->getProject()->isLoadingProject() && !getApp()->isCreatingPythonGroup()) {
+ refreshAllInputRelatedData(serialization.isNull());
+ }
_imp->runOnNodeCreatedCB(serialization.isNull());
diff --git a/Gui/GuiAppInstance.cpp b/Gui/GuiAppInstance.cpp
index 66961868ba..1cdb6e5dde 100644
--- a/Gui/GuiAppInstance.cpp
+++ b/Gui/GuiAppInstance.cpp
@@ -45,7 +45,7 @@
#include "Gui/GuiApplicationManager.h"
#include "Gui/Gui.h"
-#include "Gui/BackdropGui.h"
+#include "Gui/BackDropGui.h"
#include "Gui/NodeGraph.h"
#include "Gui/NodeGui.h"
#include "Gui/MultiInstancePanel.h"
From 677f631a630366cc6285a55ffa04ca498594111e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Devernay?=
Date: Mon, 28 Sep 2015 17:36:57 +0200
Subject: [PATCH 021/178] fix the build (beware of capitalization)
---
Gui/BackDropGui.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gui/BackDropGui.h b/Gui/BackDropGui.h
index 6863c5465d..eb82311ad7 100644
--- a/Gui/BackDropGui.h
+++ b/Gui/BackDropGui.h
@@ -17,8 +17,8 @@
* ***** END LICENSE BLOCK ***** */
-#ifndef NODEBACKDROP_H
-#define NODEBACKDROP_H
+#ifndef Gui_BackDropGui_h
+#define Gui_BackDropGui_h
// ***** BEGIN PYTHON BLOCK *****
// from :
@@ -89,4 +89,4 @@ public Q_SLOTS:
boost::scoped_ptr _imp;
};
-#endif // NODEBACKDROP_H
+#endif // Gui_BackDropGui_h
From 5d2502220b0f388a56971097c15d2545bfd4f46c Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Mon, 28 Sep 2015 18:25:10 +0200
Subject: [PATCH 022/178] Don' tassert
---
Engine/EffectInstance.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Engine/EffectInstance.cpp b/Engine/EffectInstance.cpp
index 21054840e6..5eff569e19 100644
--- a/Engine/EffectInstance.cpp
+++ b/Engine/EffectInstance.cpp
@@ -815,7 +815,9 @@ EffectInstance::getImage(int inputNb,
*/
///Check that the rendered image contains what we requested.
- assert( (!isMask && inputImg->getComponents() == comp) || (isMask && inputImg->getComponents() == maskComps) );
+ if ((!isMask && inputImg->getComponents() != comp) || (isMask && inputImg->getComponents() != maskComps)) {
+ return ImagePtr();
+ }
if (roiPixel) {
*roiPixel = pixelRoI;
From 0e2e56da11f85b92c4617d188f55805cf0ac65bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?=
Date: Tue, 29 Sep 2015 04:24:22 +0200
Subject: [PATCH 023/178] Linux: removed (old) licenses, bundle ffmpeg, minor
scripts cleanup
---
tools/linux/common.sh | 11 +-
tools/linux/include/scripts/Natron.sh | 18 +-
.../linux/include/scripts/build-installer.sh | 192 ++----------------
tools/linux/include/scripts/build-plugins.sh | 5 -
tools/linux/include/scripts/build-sdk.sh | 2 -
tools/linux/include/scripts/ffmpeg.sh | 14 ++
tools/linux/include/xml/corelibs.xml | 6 +-
tools/linux/include/xml/openfx-arena.xml | 4 -
tools/linux/include/xml/openfx-io.xml | 3 -
tools/linux/include/xml/openfx-misc.xml | 3 -
10 files changed, 50 insertions(+), 208 deletions(-)
create mode 100644 tools/linux/include/scripts/ffmpeg.sh
diff --git a/tools/linux/common.sh b/tools/linux/common.sh
index 82c19af930..dc0dc516b2 100644
--- a/tools/linux/common.sh
+++ b/tools/linux/common.sh
@@ -49,8 +49,8 @@ PACKAGES=$NATRON_PKG,$CORELIBS_PKG,$PROFILES_PKG,$IOPLUG_PKG,$MISCPLUG_PKG,$AREN
GIT_OCIO_CONFIG_TAR=https://github.com/MrKepzie/OpenColorIO-Configs/archive/Natron-v2.0.tar.gz
COLOR_PROFILES_VERSION=2.0.0
-# bump number on bugfixes
-CORELIBS_VERSION=2.0.0
+# bump timestamp on SDK changes, important!
+CORELIBS_VERSION=20150928
# SDK
#
@@ -229,3 +229,10 @@ if [ -z "$MKJOBS" ]; then
MKJOBS=$DEFAULT_MKJOBS
fi
+# License
+#
+#
+if [ "$NATRON_LICENSE" != "GPL" ] && [ "$NATRON_LICENSE" != "COMMERCIAL" ]; then
+ echo "Please select a License with NATRON_LICENSE=(GPL,COMMERCIAL)"
+ exit 1
+fi
diff --git a/tools/linux/include/scripts/Natron.sh b/tools/linux/include/scripts/Natron.sh
index efc2d8b165..9cffaf739c 100644
--- a/tools/linux/include/scripts/Natron.sh
+++ b/tools/linux/include/scripts/Natron.sh
@@ -1,5 +1,9 @@
#!/bin/bash
+#
+# Universal launch script for Natron
+#
+# Get real current dir
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do
SOURCEDIR=`dirname "$SOURCE"`
@@ -10,25 +14,31 @@ done
SOURCEDIR=`dirname "$SOURCE"`
DIR=`cd -P "$SOURCEDIR" && pwd`
+# Force numeric
export LC_NUMERIC=C
+# Set fontconfig path
+# Not needed (done in app), but added to avoid warn before splashscreen
if [ -d "$DIR/Resources/etc/fonts" ]; then
- export FONTCONFIG_PATH=$DIR/Resources/etc/fonts
+ export FONTCONFIG_PATH="$DIR/Resources/etc/fonts"
fi
+# Check for updates
if [ "$1" = "-update" -a -x "$DIR/NatronSetup" ]; then
"$DIR/NatronSetup" --updater
exit 0
fi
+# Portable mode, save settings in current dir
if [ "$1" = "-portable" ]; then
#XDG_CACHE_HOME=/tmp
- XDG_DATA_HOME=$DIR
- XDG_CONFIG_HOME=$DIR
+ XDG_DATA_HOME="$DIR"
+ XDG_CONFIG_HOME="$DIR"
export XDG_DATA_HOME XDG_CONFIG_HOME
fi
-if [ "$1" = "-debug" ]; then
+# start app, with optional debug
+if [ "$1" = "-debug" -a -x "$DIR/bin/Natron.debug" ]; then
SEGFAULT_SIGNALS="all"
export SEGFAULT_SIGNALS
catchsegv "$DIR/bin/Natron.debug" -style fusion "$@"
diff --git a/tools/linux/include/scripts/build-installer.sh b/tools/linux/include/scripts/build-installer.sh
index 95ee3cd73d..3f53989e01 100644
--- a/tools/linux/include/scripts/build-installer.sh
+++ b/tools/linux/include/scripts/build-installer.sh
@@ -73,15 +73,22 @@ mkdir -p $INSTALLER/config $INSTALLER/packages || exit 1
cat $INC_PATH/config/config.xml | sed "s/_VERSION_/${NATRON_VERSION_NUMBER}/;s#_OS_BRANCH_BIT_#${REPO_OS}#g;s#_URL_#${REPO_URL}#g" > $INSTALLER/config/config.xml || exit 1
cp $INC_PATH/config/*.png $INSTALLER/config/ || exit 1
+if [ "$NATRON_LICENSE" = "GPL" ]; then
+ FFLIC=gpl
+else
+ FFLIC=lgpl
+fi
+
# OFX IO
OFX_IO_VERSION=$TAG
OFX_IO_PATH=$INSTALLER/packages/$IOPLUG_PKG
-mkdir -p $OFX_IO_PATH/data $OFX_IO_PATH/meta $OFX_IO_PATH/data/Plugins || exit 1
+mkdir -p $OFX_IO_PATH/data $OFX_IO_PATH/meta $OFX_IO_PATH/data/Plugins $OFX_IO_PATH/data/bin || exit 1
cat $XML/openfx-io.xml | sed "s/_VERSION_/${OFX_IO_VERSION}/;s/_DATE_/${DATE}/" > $OFX_IO_PATH/meta/package.xml || exit 1
cat $QS/openfx-io.qs > $OFX_IO_PATH/meta/installscript.qs || exit 1
-cat $INSTALL_PATH/docs/openfx-io/VERSION > $OFX_IO_PATH/meta/ofx-io-license.txt || exit 1
-echo "" >> $OFX_IO_PATH/meta/ofx-io-license.txt || exit 1
-cat $INSTALL_PATH/docs/openfx-io/LICENSE >> $OFX_IO_PATH/meta/ofx-io-license.txt || exit 1
+cp $INSTALL_PATH/ffmpeg-$FFLIC/bin/{ffmpeg,ffprobe} $OFX_IO_PATH/data/bin/ || exit 1
+cat $CWD/include/scripts/ffmpeg.sh > $OFX_IO_PATH/data/ffmpeg || exit 1
+cat $CWD/include/scripts/ffmpeg.sh | sed 's/ffmpeg/ffprobe/g' > $OFX_IO_PATH/data/ffprobe || exit 1
+chmod +x $OFX_IO_PATH/data/{ffmpeg,ffprobe} || exit 1
cp -a $INSTALL_PATH/Plugins/IO.ofx.bundle $OFX_IO_PATH/data/Plugins/ || exit 1
strip -s $OFX_IO_PATH/data/Plugins/*/*/*/*
IO_LIBS=$OFX_IO_PATH/data/Plugins/IO.ofx.bundle/Libraries
@@ -92,17 +99,7 @@ for x in $OFX_DEPENDS; do
cp -v $x $IO_LIBS/ || exit 1
done
-if [ "$NATRON_LICENSE" != "GPL" ] && [ "$NATRON_LICENSE" != "COMMERCIAL" ]; then
- echo "Please select a License with NATRON_LICENSE=(GPL,COMMERCIAL)"
- exit 1
-fi
-
-if [ "$NATRON_LICENSE" = "GPL" ]; then
- FFLIC=gpl
-else
- FFLIC=lgpl
-fi
-cp -v $INSTALL_PATH/ffmpeg-$FFLIC/lib/{libavformat.so.56,libavcodec.so.56,libswscale.so.3,libavutil.so.54,libswresample.so.1} $IO_LIBS/ || exit 1
+cp -v $INSTALL_PATH/ffmpeg-$FFLIC/lib/{libavfilter.so.5,libavdevice.so.56,libpostproc.so.53,libavresample.so.2,libavformat.so.56,libavcodec.so.56,libswscale.so.3,libavutil.so.54,libswresample.so.1} $IO_LIBS/ || exit 1
OFX_LIB_DEP=$(ldd $IO_LIBS/*|grep opt | awk '{print $3}')
for y in $OFX_LIB_DEP; do
cp -v $y $IO_LIBS/ || exit 1
@@ -123,148 +120,12 @@ rm -f $IO_LIBS/{libgcc*,libstdc*,libbz2*,libfont*,libfree*,libpng*,libjpeg*,libt
)
strip -s $IO_LIBS/*
-IO_LIC=$OFX_IO_PATH/meta/ofx-io-license.txt
-echo "" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-echo "BOOST:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/boost/LICENSE_1_0.txt >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "FFMPEG:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-if [ "$NATRON_LICENSE" = "GPL" ]; then
- cat $INSTALL_PATH/docs/ffmpeg/COPYING.GPLv3 >> $IO_LIC || exit 1
-else
- cat $INSTALL_PATH/docs/ffmpeg/COPYING.LGPLv2.1 >>$IO_LIC || exit 1
-fi
-
-echo "" >>$IO_LIC || exit 1
-echo "JPEG:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/jpeg/README >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "OPENCOLORIO:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/ocio/LICENSE >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "OPENIMAGEIO:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/oiio/LICENSE >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "OPENEXR:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/openexr/LICENSE >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "OPENJPEG:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/openjpeg/LICENSE >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "PNG:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/png/LICENSE >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "TIFF:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/tiff/COPYRIGHT >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "SEEXPR:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/seexpr/license.txt >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "LIBRAW:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/libraw/COPYRIGHT >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "JASPER:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/jasper/COPYRIGHT >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "LCMS:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/lcms/COPYING >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "DIRAC:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/dirac/COPYING.MPL >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "LAME:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/lame/COPYING >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "MODPLUG:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/libmodplug/COPYING >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "OGG:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/libogg/COPYING >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "THEORA:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/libtheora/COPYING >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "VORBIS:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/libvorbis/COPYING >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "VPX:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/libvpx/LICENSE >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "OPUS:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/opus/COPYING >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "ORC:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/orc/COPYING >>$IO_LIC || exit 1
-
-echo "" >>$IO_LIC || exit 1
-echo "SPEEX:" >>$IO_LIC || exit 1
-echo "" >>$IO_LIC || exit 1
-cat $INSTALL_PATH/docs/speex/COPYING >>$IO_LIC || exit 1
-
-if [ "$NATRON_LICENSE" = "GPL" ]; then
- echo "" >>$IO_LIC || exit 1
- echo "X264:" >>$IO_LIC || exit 1
- echo "" >>$IO_LIC || exit 1
- cat $INSTALL_PATH/docs/x264/COPYING >>$IO_LIC || exit 1
-
- echo "" >>$IO_LIC || exit 1
- echo "XVID:" >>$IO_LIC || exit 1
- echo "" >>$IO_LIC || exit 1
- cat $INSTALL_PATH/docs/xvidcore/LICENSE >>$IO_LIC || exit 1
-fi
-
# OFX MISC
OFX_MISC_VERSION=$TAG
OFX_MISC_PATH=$INSTALLER/packages/$MISCPLUG_PKG
mkdir -p $OFX_MISC_PATH/data $OFX_MISC_PATH/meta $OFX_MISC_PATH/data/Plugins || exit 1
cat $XML/openfx-misc.xml | sed "s/_VERSION_/${OFX_MISC_VERSION}/;s/_DATE_/${DATE}/" > $OFX_MISC_PATH/meta/package.xml || exit 1
cat $QS/openfx-misc.qs > $OFX_MISC_PATH/meta/installscript.qs || exit 1
-cat $INSTALL_PATH/docs/openfx-misc/VERSION > $OFX_MISC_PATH/meta/ofx-misc-license.txt || exit 1
-echo "" >> $OFX_MISC_PATH/meta/ofx-misc-license.txt || exit 1
-cat $INSTALL_PATH/docs/openfx-misc/LICENSE >> $OFX_MISC_PATH/meta/ofx-misc-license.txt || exit 1
cp -a $INSTALL_PATH/Plugins/{CImg,Misc}.ofx.bundle $OFX_MISC_PATH/data/Plugins/ || exit 1
strip -s $OFX_MISC_PATH/data/Plugins/*/*/*/*
CIMG_LIBS=$OFX_MISC_PATH/data/Plugins/CImg.ofx.bundle/Libraries
@@ -302,10 +163,6 @@ if [ -f "$NATRON_PATH/data/bin/NatronCrashReporter" ]; then
strip -s $NATRON_PATH/data/bin/NatronCrashReporter $NATRON_PATH/data/bin/NatronRendererCrashReporter
fi
-# most (all) distros has ffmpeg in the repository
-#cp $INSTALL_PATH/ffmpeg-${FFLIC}/bin/ffmpeg $NATRON_PATH/data/bin/ || exit 1
-#cp $INSTALL_PATH/ffmpeg-${FFLIC}/bin/ffprobe $NATRON_PATH/data/bin/ || exit 1
-
wget $NATRON_API_DOC || exit 1
mv natron.pdf $NATRON_PATH/data/docs/Natron_Python_API_Reference.pdf || exit 1
rm $NATRON_PATH/data/docs/TuttleOFX-README.txt || exit 1
@@ -368,23 +225,6 @@ cp -a $INSTALL_PATH/etc/fonts $CLIBS_PATH/data/share/etc/ || exit 1
strip -s $CLIBS_PATH/data/lib/*
strip -s $CLIBS_PATH/data/bin/*/*
-CORE_DOC=$CLIBS_PATH
-cat $INSTALL_PATH/docs/boost/LICENSE_1_0.txt >> $CORE_DOC/meta/3rdparty-license.txt
-cat $INSTALL_PATH/docs/cairo/COPYING-MPL-1.1 >> $CORE_DOC/meta/3rdparty-license.txt
-cat $INSTALL_PATH/docs/glew/LICENSE.txt >> $CORE_DOC/meta/3rdparty-license.txt
-cat $INSTALL_PATH/docs/jpeg/README >> $CORE_DOC/meta/3rdparty-license.txt
-cat $INSTALL_PATH/docs/png/LICENSE >> $CORE_DOC/meta/3rdparty-license.txt
-cat $INSTALL_PATH/docs/qt/*LGPL* >> $CORE_DOC/meta/3rdparty-license.txt
-cat $INSTALL_PATH/docs/tiff/COPYRIGHT >> $CORE_DOC/meta/3rdparty-license.txt
-
-if [ "$PYV" = "3" ]; then
- cat $INSTALL_PATH/docs/python3/LICENSE >> $CORE_DOC/meta/3rdparty-license.txt || exit 1
-else
- cat $INSTALL_PATH/docs/python2/LICENSE >> $CORE_DOC/meta/3rdparty-license.txt || exit 1
-fi
-cat $INSTALL_PATH/docs/pyside/* >> $CORE_DOC/meta/3rdparty-license.txt
-cat $INSTALL_PATH/docs/shibroken/* >> $CORE_DOC/meta/3rdparty-license.txt
-
#Copy Python distrib
mkdir -p $CLIBS_PATH/data/Plugins || exit 1
if [ "$PYV" = "3" ]; then
@@ -398,7 +238,6 @@ else
(cd $CLIBS_PATH/data/lib/python2.7/site-packages; ln -sf ../../../Plugins/PySide . )
rm -rf $CLIBS_PATH/data/lib/python2.7/{test,config} || exit 1
fi
-#rm -f $CLIBS_PATH/data/Plugins/PySide/{QtDeclarative,QtHelp,QtScript,QtScriptTools,QtSql,QtTest,QtUiTools,QtXmlPatterns}.so || exit 1
PY_DEPENDS=$(ldd $CLIBS_PATH/data/Plugins/PySide/*|grep opt | awk '{print $3}')
for y in $PY_DEPENDS; do
cp -v $y $CLIBS_PATH/data/lib/ || exit 1
@@ -412,15 +251,8 @@ OFX_ARENA_PATH=$INSTALLER/packages/$ARENAPLUG_PKG
mkdir -p $OFX_ARENA_PATH/meta $OFX_ARENA_PATH/data/Plugins || exit 1
cat $XML/openfx-arena.xml | sed "s/_VERSION_/${OFX_ARENA_VERSION}/;s/_DATE_/${DATE}/" > $OFX_ARENA_PATH/meta/package.xml || exit 1
cat $QS/openfx-arena.qs > $OFX_ARENA_PATH/meta/installscript.qs || exit 1
-cat $INSTALL_PATH/docs/openfx-arena/VERSION > $OFX_ARENA_PATH/meta/ofx-extra-license.txt || exit 1
-echo "" >> $OFX_ARENA_PATH/meta/ofx-extra-license.txt || exit 1
-cat $INSTALL_PATH/docs/openfx-arena/LICENSE >> $OFX_ARENA_PATH/meta/ofx-extra-license.txt || exit 1
cp -av $INSTALL_PATH/Plugins/Arena.ofx.bundle $OFX_ARENA_PATH/data/Plugins/ || exit 1
strip -s $OFX_ARENA_PATH/data/Plugins/*/*/*/*
-echo "ImageMagick License:" >> $OFX_ARENA_PATH/meta/ofx-extra-license.txt || exit 1
-cat $INSTALL_PATH/docs/imagemagick/LICENSE >> $OFX_ARENA_PATH/meta/ofx-extra-license.txt || exit 1
-echo "LCMS License:" >>$OFX_ARENA_PATH/meta/ofx-extra-license.txt || exit 1
-cat $INSTALL_PATH/docs/lcms/COPYING >>$OFX_ARENA_PATH/meta/ofx-extra-license.txt || exit 1
ARENA_LIBS=$OFX_ARENA_PATH/data/Plugins/Arena.ofx.bundle/Libraries
mkdir -p $ARENA_LIBS || exit 1
diff --git a/tools/linux/include/scripts/build-plugins.sh b/tools/linux/include/scripts/build-plugins.sh
index fb8a4228fa..0e45007b9f 100644
--- a/tools/linux/include/scripts/build-plugins.sh
+++ b/tools/linux/include/scripts/build-plugins.sh
@@ -61,11 +61,6 @@ else
export LD_LIBRARY_PATH=$INSTALL_PATH/gcc/lib:$LD_LIBRARY_PATH
fi
-if [ "$NATRON_LICENSE" != "GPL" ] && [ "$NATRON_LICENSE" != "COMMERCIAL" ]; then
- echo "Please select a License with NATRON_LICENSE=(GPL,COMMERCIAL)"
- exit 1
-fi
-
if [ "$NATRON_LICENSE" = "GPL" ]; then
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$INSTALL_PATH/ffmpeg-gpl/lib/pkgconfig
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$INSTALL_PATH/ffmpeg-gpl/lib
diff --git a/tools/linux/include/scripts/build-sdk.sh b/tools/linux/include/scripts/build-sdk.sh
index 5f50d9969e..437651cd60 100644
--- a/tools/linux/include/scripts/build-sdk.sh
+++ b/tools/linux/include/scripts/build-sdk.sh
@@ -250,8 +250,6 @@ fi
# Setup env
PKG_CONFIG_PATH="$INSTALL_PATH/lib/pkgconfig"
-#LD_LIBRARY_PATH="$INSTALL_PATH/lib"
-#PATH="$INSTALL_PATH/bin:$PATH"
QTDIR="$INSTALL_PATH"
BOOST_ROOT="$INSTALL_PATH"
OPENJPEG_HOME="$INSTALL_PATH"
diff --git a/tools/linux/include/scripts/ffmpeg.sh b/tools/linux/include/scripts/ffmpeg.sh
new file mode 100644
index 0000000000..08248fb0e5
--- /dev/null
+++ b/tools/linux/include/scripts/ffmpeg.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+SOURCE="${BASH_SOURCE[0]}"
+while [ -h "$SOURCE" ]; do
+ SOURCEDIR=`dirname "$SOURCE"`
+ DIR=`cd -P "$SOURCEDIR" && pwd`
+ SOURCE="$(readlink "$SOURCE")"
+ [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
+done
+SOURCEDIR=`dirname "$SOURCE"`
+DIR=`cd -P "$SOURCEDIR" && pwd`
+
+export LD_LIBRARY_PATH="$DIR/lib:$DIR/Plugins/IO.ofx.bundle/Libraries"
+"$DIR/bin/ffmpeg" "$@"
diff --git a/tools/linux/include/xml/corelibs.xml b/tools/linux/include/xml/corelibs.xml
index 07e6fc56b1..bff5f85f07 100644
--- a/tools/linux/include/xml/corelibs.xml
+++ b/tools/linux/include/xml/corelibs.xml
@@ -1,14 +1,10 @@
Natron Libraries
- Libraries needed by Natron.
+ Libraries needed by Natron and plugins.
_VERSION_
_DATE_
fr.inria.natron.libs
-
-
-
-
script
diff --git a/tools/linux/include/xml/openfx-arena.xml b/tools/linux/include/xml/openfx-arena.xml
index c9b4f43952..557a517280 100644
--- a/tools/linux/include/xml/openfx-arena.xml
+++ b/tools/linux/include/xml/openfx-arena.xml
@@ -6,10 +6,6 @@
_DATE_
fr.inria.openfx.extra
fr.inria.natron
-
-
-
-
script
diff --git a/tools/linux/include/xml/openfx-io.xml b/tools/linux/include/xml/openfx-io.xml
index a5fbbde3a4..699b9af2ae 100644
--- a/tools/linux/include/xml/openfx-io.xml
+++ b/tools/linux/include/xml/openfx-io.xml
@@ -6,9 +6,6 @@
_DATE_
fr.inria.openfx.io
fr.inria.natron
-
-
-
1234
script
diff --git a/tools/linux/include/xml/openfx-misc.xml b/tools/linux/include/xml/openfx-misc.xml
index cc4e464ef1..046c7093cb 100644
--- a/tools/linux/include/xml/openfx-misc.xml
+++ b/tools/linux/include/xml/openfx-misc.xml
@@ -6,9 +6,6 @@
_DATE_
fr.inria.openfx.misc
fr.inria.natron
-
-
-
1234
script
From 7727598828d8ca6e34f0fa42f549c1eed06207f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?=
Date: Tue, 29 Sep 2015 04:36:10 +0200
Subject: [PATCH 024/178] Linux: fix cache path in fonts.conf
---
tools/linux/include/scripts/build-installer.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/linux/include/scripts/build-installer.sh b/tools/linux/include/scripts/build-installer.sh
index 3f53989e01..85a2e92d4e 100644
--- a/tools/linux/include/scripts/build-installer.sh
+++ b/tools/linux/include/scripts/build-installer.sh
@@ -218,6 +218,7 @@ mv $IO_LIBS/{libOpenColor*,libgomp*} $CLIBS_PATH/data/lib/ || exit 1
mkdir -p $CLIBS_PATH/data/share/etc || exit 1
cp -a $INSTALL_PATH/etc/fonts $CLIBS_PATH/data/share/etc/ || exit 1
+sed -i "s#/opt/Natron-${SDK_VERSION}/#/#" $CLIBS_PATH/data/share/etc/fonts/fonts.conf || exit 1
(cd $CLIBS_PATH/data ; ln -sf share Resources )
# TODO: At this point send unstripped binaries (and debug binaries?) to Socorro server for breakpad
From 914620ad9532bbb58b5fce393441077706439871 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?=
Date: Tue, 29 Sep 2015 05:01:36 +0200
Subject: [PATCH 025/178] Linux: update centos build instructions, fixed forced
path in build-installer
---
INSTALL_LINUX.md | 18 +++++-------------
tools/linux/include/scripts/build-installer.sh | 2 +-
2 files changed, 6 insertions(+), 14 deletions(-)
diff --git a/INSTALL_LINUX.md b/INSTALL_LINUX.md
index e35a820def..5a3540245d 100644
--- a/INSTALL_LINUX.md
+++ b/INSTALL_LINUX.md
@@ -151,19 +151,14 @@ You must copy them to a directory named `../share/OpenColorIO-Configs` relative
pacman -S qt4 cairo glew python expat boost pixman ffmpeg opencolorio openimageio wget git cmake gcc make libxslt pkg-config
wget https://raw.githubusercontent.com/olear/natron-linux/master/include/misc/build-natron-on-archlinux.sh
-## CentOS6
-
-### Add devtools-2
-```
-wget http://people.centos.org/tru/devtools-2/devtools-2.repo -O /etc/yum.repos.d/devtools-2.repo
-```
+## CentOS6+ (64-bit)
### Install dependencies
```
-yum -y install libxslt-devel pango-devel librsvg2-devel libxml2-devel devtoolset-2-toolchain gcc-c++ kernel-devel libX*devel fontconfig-devel freetype-devel zlib-devel *GL*devel *xcb*devel xorg*devel libdrm-devel mesa*devel *glut*devel dbus-devel bzip2-devel glib2-devel bison flex expat-devel libtool-ltdl-devel git
+yum -y install gcc-c++ wget libX*devel *GL*devel *xcb*devel xorg*devel libdrm-devel mesa*devel *glut*devel dbus-devel bison flex expat-devel libtool-ltdl-devel git make glibc-devel glibc-devel.i686
```
-### Download SDK
+### Download SDK (third-party software)
```
wget http://downloads.natron.fr/Third_Party_Binaries/Natron-CY2015-Linux-x86_64-SDK.tar.xz
tar xvf Natron-CY2015-Linux-x86_64-SDK.tar.xz -C /opt/
@@ -180,18 +175,15 @@ for i in $(echo "Natron openfx-io openfx-misc openfx-arena");do cd $i ; git subm
### Build Natron and plugins
```
-scl enable devtoolset-2 bash
export INSTALL_PATH=/opt/Natron-CY2015
export PKG_CONFIG_PATH=$INSTALL_PATH/lib/pkgconfig:$INSTALL_PATH/ffmpeg-gpl/lib/pkgconfig
-export LD_LIBRARY_PATH=$INSTALL_PATH/lib:$INSTALL_PATH/ffmpeg-gpl/lib
-export PATH=/usr/local/bin:$INSTALL_PATH/bin:$INSTALL_PATH/ffmpeg-gpl/bin:$PATH
+export LD_LIBRARY_PATH=$INSTALL_PATH/gcc/lib64:$INSTALL_PATH/lib:$INSTALL_PATH/ffmpeg-gpl/lib
+export PATH=$INSTALL_PATH/gcc/bin:$INSTALL_PATH/bin:$INSTALL_PATH/ffmpeg-gpl/bin:$PATH
export QTDIR=$INSTALL_PATH
export BOOST_ROOT=$INSTALL_PATH
export PYTHON_HOME=$INSTALL_PATH
export PYTHON_PATH=$INSTALL_PATH/lib/python2.7
export PYTHON_INCLUDE=$INSTALL_PATH/include/python2.7
-export OPENJPEG_HOME=$INSTALL_PATH
-export THIRD_PARTY_TOOLS_HOME=$INSTALL_PATH
cd Natron
wget https://raw.githubusercontent.com/MrKepzie/Natron/workshop/tools/linux/include/natron/config.pri
diff --git a/tools/linux/include/scripts/build-installer.sh b/tools/linux/include/scripts/build-installer.sh
index 85a2e92d4e..c4c127939e 100644
--- a/tools/linux/include/scripts/build-installer.sh
+++ b/tools/linux/include/scripts/build-installer.sh
@@ -218,7 +218,7 @@ mv $IO_LIBS/{libOpenColor*,libgomp*} $CLIBS_PATH/data/lib/ || exit 1
mkdir -p $CLIBS_PATH/data/share/etc || exit 1
cp -a $INSTALL_PATH/etc/fonts $CLIBS_PATH/data/share/etc/ || exit 1
-sed -i "s#/opt/Natron-${SDK_VERSION}/#/#" $CLIBS_PATH/data/share/etc/fonts/fonts.conf || exit 1
+sed -i "s#${SDK_PATH}/Natron-${SDK_VERSION}/#/#" $CLIBS_PATH/data/share/etc/fonts/fonts.conf || exit 1
(cd $CLIBS_PATH/data ; ln -sf share Resources )
# TODO: At this point send unstripped binaries (and debug binaries?) to Socorro server for breakpad
From 856db83cc62ab40636cbbc6d5999e8f1cb5cedff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Devernay?=
Date: Tue, 29 Sep 2015 08:16:04 +0200
Subject: [PATCH 026/178] Viewer: correct a few tooltips (don't use the future
when things happen in the present)
---
Gui/ViewerTab.cpp | 45 +++++++++++++++++++++++++--------------------
1 file changed, 25 insertions(+), 20 deletions(-)
diff --git a/Gui/ViewerTab.cpp b/Gui/ViewerTab.cpp
index 7eb1d44b71..b8e7a25cc0 100644
--- a/Gui/ViewerTab.cpp
+++ b/Gui/ViewerTab.cpp
@@ -314,14 +314,14 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
addSpacer(_imp->firstRowLayout);
_imp->firstInputLabel = new Natron::Label("A:",_imp->firstSettingsRow);
+ _imp->firstInputLabel->setToolTip(Natron::convertFromPlainText(tr("Viewer input A."), Qt::WhiteSpaceNormal));
_imp->firstRowLayout->addWidget(_imp->firstInputLabel);
_imp->firstInputImage = new ComboBox(_imp->firstSettingsRow);
-
+ _imp->firstInputImage->setToolTip(_imp->firstInputLabel->toolTip());
_imp->firstInputImage->setFixedWidth(fm.width("ColorCorrect1") + 3 * DROP_DOWN_ICON_SIZE);
_imp->firstInputImage->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
_imp->firstInputImage->addItem(" - ");
-
QObject::connect( _imp->firstInputImage,SIGNAL( currentIndexChanged(QString) ),this,SLOT( onFirstInputNameChanged(QString) ) );
_imp->firstRowLayout->addWidget(_imp->firstInputImage);
@@ -329,6 +329,7 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
appPTR->getIcon(NATRON_PIXMAP_MERGE_GROUPING, NATRON_MEDIUM_BUTTON_ICON_SIZE, &pixMerge);
_imp->compositingOperatorLabel = new Natron::Label("",_imp->firstSettingsRow);
_imp->compositingOperatorLabel->setPixmap(pixMerge);
+ _imp->compositingOperatorLabel->setToolTip(Natron::convertFromPlainText(tr("Operation applied between viewer inputs A and B."), Qt::WhiteSpaceNormal));
_imp->firstRowLayout->addWidget(_imp->compositingOperatorLabel);
@@ -336,6 +337,7 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
QObject::connect( _imp->compositingOperator,SIGNAL( currentIndexChanged(int) ),this,SLOT( onCompositingOperatorIndexChanged(int) ) );
_imp->compositingOperator->setFixedWidth(fm.width("Minus") + 3 * DROP_DOWN_ICON_SIZE);
_imp->compositingOperator->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ _imp->compositingOperator->setToolTip(_imp->compositingOperatorLabel->toolTip());
_imp->compositingOperator->addItem(tr(" - "), QIcon(), QKeySequence(), tr("Only the A input is used."));
_imp->compositingOperator->addItem(tr("Over"), QIcon(), QKeySequence(), tr("A + B(1 - Aalpha)"));
_imp->compositingOperator->addItem(tr("Under"), QIcon(), QKeySequence(), tr("A(1 - Balpha) + B"));
@@ -347,13 +349,15 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
_imp->firstRowLayout->addWidget(_imp->compositingOperator);
_imp->secondInputLabel = new Natron::Label("B:",_imp->firstSettingsRow);
+ _imp->secondInputLabel->setToolTip(Natron::convertFromPlainText(tr("Viewer input B."), Qt::WhiteSpaceNormal));
_imp->firstRowLayout->addWidget(_imp->secondInputLabel);
_imp->secondInputImage = new ComboBox(_imp->firstSettingsRow);
- QObject::connect( _imp->secondInputImage,SIGNAL( currentIndexChanged(QString) ),this,SLOT( onSecondInputNameChanged(QString) ) );
+ _imp->secondInputImage->setToolTip(_imp->secondInputLabel->toolTip());
_imp->secondInputImage->setFixedWidth(fm.width("ColorCorrect1") + 3 * DROP_DOWN_ICON_SIZE);
_imp->secondInputImage->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
_imp->secondInputImage->addItem(" - ");
+ QObject::connect( _imp->secondInputImage,SIGNAL( currentIndexChanged(QString) ),this,SLOT( onSecondInputNameChanged(QString) ) );
_imp->firstRowLayout->addWidget(_imp->secondInputImage);
_imp->firstRowLayout->addStretch();
@@ -422,11 +426,11 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
_imp->toggleGammaButton->setFocusPolicy(Qt::NoFocus);
_imp->toggleGammaButton->setFixedSize(NATRON_MEDIUM_BUTTON_SIZE, NATRON_MEDIUM_BUTTON_SIZE);
_imp->toggleGammaButton->setIconSize(QSize(NATRON_MEDIUM_BUTTON_ICON_SIZE, NATRON_MEDIUM_BUTTON_ICON_SIZE));
- _imp->toggleGammaButton->setToolTip(Natron::convertFromPlainText(tr("Switch between gamma at 1.0 and the previous setting"), Qt::WhiteSpaceNormal));
+ _imp->toggleGammaButton->setToolTip(Natron::convertFromPlainText(tr("Viewer gamma correction: switch between gamma=1.0 and user setting."), Qt::WhiteSpaceNormal));
_imp->secondRowLayout->addWidget(_imp->toggleGammaButton);
_imp->gammaBox = new SpinBox(_imp->secondSettingsRow, SpinBox::eSpinBoxTypeDouble);
- QString gammaTt = Natron::convertFromPlainText(tr("Gamma correction. It is applied after gain and before colorspace correction"), Qt::WhiteSpaceNormal);
+ QString gammaTt = Natron::convertFromPlainText(tr("Viewer gamma correction level (applied after gain and before colorspace correction)."), Qt::WhiteSpaceNormal);
_imp->gammaBox->setToolTip(gammaTt);
QObject::connect(_imp->gammaBox,SIGNAL(valueChanged(double)), this, SLOT(onGammaSpinBoxValueChanged(double)));
_imp->gammaBox->setValue(1.0);
@@ -463,7 +467,7 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
_imp->checkerboardButton->setChecked(false);
_imp->checkerboardButton->setDown(false);
_imp->checkerboardButton->setToolTip(Natron::convertFromPlainText(tr("If checked, the viewer draws a checkerboard under the image instead of black "
- "(within the project window only)."), Qt::WhiteSpaceNormal));
+ "(only within the project window)."), Qt::WhiteSpaceNormal));
_imp->checkerboardButton->setFixedSize(NATRON_MEDIUM_BUTTON_SIZE, NATRON_MEDIUM_BUTTON_SIZE);
_imp->checkerboardButton->setIconSize(QSize(NATRON_MEDIUM_BUTTON_ICON_SIZE, NATRON_MEDIUM_BUTTON_ICON_SIZE));
QObject::connect(_imp->checkerboardButton,SIGNAL(clicked(bool)),this,SLOT(onCheckerboardButtonClicked()));
@@ -676,16 +680,17 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
//QFont font(appFont,appFontSize);
- _imp->canEditFrameRangeLabel = new ClickableLabel(tr("Frame range"),_imp->playerButtonsContainer);
+ _imp->canEditFrameRangeLabel = new ClickableLabel(tr("Playback range"),_imp->playerButtonsContainer);
//_imp->canEditFrameRangeLabel->setFont(font);
_imp->playerLayout->addWidget(_imp->canEditFrameRangeLabel);
_imp->frameRangeEdit = new LineEdit(_imp->playerButtonsContainer);
QObject::connect( _imp->frameRangeEdit,SIGNAL( editingFinished() ),this,SLOT( onFrameRangeEditingFinished() ) );
- _imp->frameRangeEdit->setToolTip( Natron::convertFromPlainText(tr("Define here the timeline bounds in which the cursor will playback. Alternatively"
- " you can drag the red markers on the timeline. The frame range of the project "
- "is the part coloured in grey on the timeline."),
+ _imp->frameRangeEdit->setToolTip( Natron::convertFromPlainText(tr("Timeline bounds for video playback. It may be edited by dragging"
+ " the red markers on the timeline using Ctrl+click+drag. This is "
+ "different from the project frame range, which "
+ "is displayed on the timeline with a lighter background."),
Qt::WhiteSpaceNormal) );
boost::shared_ptr timeline = _imp->app->getTimeLine();
_imp->frameRangeEdit->setMaximumWidth(70);
@@ -703,7 +708,7 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
tripleSyncIc.addPixmap(tripleSyncUnlockPix, QIcon::Normal, QIcon::Off);
tripleSyncIc.addPixmap(tripleSyncLockedPix, QIcon::Normal, QIcon::On);
_imp->tripleSyncButton = new Button(tripleSyncIc,"",_imp->playerButtonsContainer);
- _imp->tripleSyncButton->setToolTip(Natron::convertFromPlainText(tr("When activated, timeline's frame-range will be synchronized with the Dope Sheet and the Curve Editor as well."),Qt::WhiteSpaceNormal));
+ _imp->tripleSyncButton->setToolTip(Natron::convertFromPlainText(tr("When activated, the timeline frame-range is synchronized with the Dope Sheet and the Curve Editor."),Qt::WhiteSpaceNormal));
_imp->tripleSyncButton->setCheckable(true);
_imp->tripleSyncButton->setChecked(false);
_imp->tripleSyncButton->setFixedSize(NATRON_MEDIUM_BUTTON_SIZE,NATRON_MEDIUM_BUTTON_SIZE);
@@ -718,10 +723,10 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
_imp->canEditFpsBox = new QCheckBox(_imp->playerButtonsContainer);
- QString canEditFpsBoxTT = Natron::convertFromPlainText(tr("When unchecked, the frame rate will be automatically set by "
- " the informations of the input stream of the Viewer. "
- "When checked, you're free to set the frame rate of the Viewer.")
- , Qt::WhiteSpaceNormal);
+ QString canEditFpsBoxTT = Natron::convertFromPlainText(tr("When unchecked, the playback frame rate is automatically set from "
+ " the Viewer A input. "
+ "When checked, the user setting is used.")
+ , Qt::WhiteSpaceNormal);
_imp->canEditFpsBox->setFixedSize(NATRON_MEDIUM_BUTTON_SIZE, NATRON_MEDIUM_BUTTON_SIZE);
_imp->canEditFpsBox->setIconSize(QSize(NATRON_MEDIUM_BUTTON_ICON_SIZE, NATRON_MEDIUM_BUTTON_ICON_SIZE));
@@ -743,7 +748,7 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
_imp->fpsBox->setValue(24.0);
_imp->fpsBox->setIncrement(0.1);
_imp->fpsBox->setToolTip( "" + tr("fps:") + "
" + tr(
- "Enter here the desired playback rate.") );
+ "Viewer playback framerate.") );
_imp->playerLayout->addWidget(_imp->fpsBox);
@@ -760,8 +765,8 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
_imp->turboButton->setFixedSize(NATRON_MEDIUM_BUTTON_SIZE, NATRON_MEDIUM_BUTTON_SIZE);
_imp->turboButton->setIconSize(QSize(NATRON_MEDIUM_BUTTON_ICON_SIZE, NATRON_MEDIUM_BUTTON_ICON_SIZE));
_imp->turboButton->setToolTip("" + tr("Turbo mode:") + "
" +
- tr("When checked, everything besides the viewer will not be refreshed in the user interface "
- "for maximum efficiency during playback.") + "
");
+ tr("When checked, only the viewer is redrawn during playback, "
+ "for maximum efficiency.") + "
");
_imp->turboButton->setFocusPolicy(Qt::NoFocus);
QObject::connect( _imp->turboButton, SIGNAL (clicked(bool)), getGui(), SLOT(onFreezeUIButtonClicked(bool) ) );
_imp->playerLayout->addWidget(_imp->turboButton);
@@ -862,14 +867,14 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
tr("Clips the portion of the image displayed "
"on the viewer to the project format. "
"When off, everything in the union of all nodes "
- "region of definition will be displayed.") +"" +
+ "region of definition is displayed.") +"" +
"" + tr("Keyboard shortcut") + ": %1
", _imp->clipToProjectFormatButton);
QStringList roiActions;
roiActions << kShortcutIDActionROIEnabled;
roiActions << kShortcutIDActionNewROI;
setTooltipWithShortcut2(kShortcutGroupViewer, roiActions,"" +
- tr("When active, enables the region of interest that will limit"
+ tr("When active, enables the region of interest that limits"
" the portion of the viewer that is kept updated.") +"
" +
"" + tr("Keyboard shortcut") + ": %1
" +
"" + tr("Press ") + " %2 " + tr("to activate and drag a new region.") + "
", _imp->enableViewerRoI);
From 87a16d3d7a9dc0d01eae3fbf604994c4b9444c92 Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Tue, 29 Sep 2015 09:32:07 +0200
Subject: [PATCH 027/178] Don't fail, print a warning instead
---
Engine/EffectInstance.cpp | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/Engine/EffectInstance.cpp b/Engine/EffectInstance.cpp
index 5eff569e19..5f7ef39376 100644
--- a/Engine/EffectInstance.cpp
+++ b/Engine/EffectInstance.cpp
@@ -599,11 +599,11 @@ EffectInstance::getImage(int inputNb,
return ImagePtr();
}
- std::list outputClipPrefComps;
+ /*std::list outputClipPrefComps;
ImageBitDepthEnum outputDepth;
getPreferredDepthAndComponents(inputNb, &outputClipPrefComps, &outputDepth);
assert(outputClipPrefComps.size() >= 1);
- const ImageComponents & prefComps = outputClipPrefComps.front();
+ const ImageComponents & prefComps = outputClipPrefComps.front();*/
///If optionalBounds have been set, use this for the RoI instead of the data int the TLS
RectD optionalBounds;
@@ -743,9 +743,9 @@ EffectInstance::getImage(int inputNb,
assert(attachedStroke);
if (attachedStroke) {
if (duringPaintStroke) {
- inputImg = getNode()->getOrRenderLastStrokeImage(mipMapLevel, pixelRoI, par, prefComps, depth);
+ inputImg = getNode()->getOrRenderLastStrokeImage(mipMapLevel, pixelRoI, par, comp, depth);
} else {
- inputImg = roto->renderMaskFromStroke(attachedStroke, pixelRoI, prefComps,
+ inputImg = roto->renderMaskFromStroke(attachedStroke, pixelRoI, comp,
time, view, depth, mipMapLevel);
if ( roto->isDoingNeatRender() ) {
getNode()->updateStrokeImage(inputImg);
@@ -814,11 +814,26 @@ EffectInstance::getImage(int inputNb,
* instantaneous thanks to the image cache.
*/
+#ifdef DEBUG
///Check that the rendered image contains what we requested.
if ((!isMask && inputImg->getComponents() != comp) || (isMask && inputImg->getComponents() != maskComps)) {
- return ImagePtr();
+ ImageComponents cc;
+ if (isMask) {
+ cc = maskComps;
+ } else {
+ cc = comp;
+ }
+ qDebug() << "WARNING:"<< getNode()->getScriptName_mt_safe().c_str() << "requested" << cc.getComponentsGlobalName().c_str() << "but" << n->getScriptName_mt_safe().c_str() << "returned an image with"
+ << inputImg->getComponents().getComponentsGlobalName().c_str();
+ std::list prefComps;
+ ImageBitDepthEnum depth;
+ n->getPreferredDepthAndComponents(-1, &prefComps, &depth);
+ assert(!prefComps.empty());
+ qDebug() << n->getScriptName_mt_safe().c_str() << "output clip preferences is" << prefComps.front().getComponentsGlobalName().c_str();
}
+#endif
+
if (roiPixel) {
*roiPixel = pixelRoI;
}
@@ -845,16 +860,16 @@ EffectInstance::getImage(int inputNb,
}
- if ( prefComps.getNumComponents() != inputImg->getComponents().getNumComponents() ) {
+ if ( comp.getNumComponents() != inputImg->getComponents().getNumComponents() ) {
ImagePtr remappedImg;
{
Image::ReadAccess acc = inputImg->getReadRights();
- remappedImg.reset( new Image(prefComps, inputImg->getRoD(), inputImg->getBounds(), inputImg->getMipMapLevel(), inputImg->getPixelAspectRatio(), inputImg->getBitDepth(), false) );
+ remappedImg.reset( new Image(comp, inputImg->getRoD(), inputImg->getBounds(), inputImg->getMipMapLevel(), inputImg->getPixelAspectRatio(), inputImg->getBitDepth(), false) );
Natron::ViewerColorSpaceEnum colorspace = getApp()->getDefaultColorSpaceForBitDepth( inputImg->getBitDepth() );
bool unPremultIfNeeded = getOutputPremultiplication() == eImagePremultiplicationPremultiplied &&
- inputImg->getComponents().getNumComponents() == 4 && prefComps.getNumComponents() == 3;
+ inputImg->getComponents().getNumComponents() == 4 && comp.getNumComponents() == 3;
inputImg->convertToFormat( inputImg->getBounds(),
colorspace, colorspace,
channelForMask, false, unPremultIfNeeded, remappedImg.get() );
From a0e3aa171f3022ac5cbd882f64eedb4070cfe393 Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Tue, 29 Sep 2015 10:04:53 +0200
Subject: [PATCH 028/178] Abort: bug fix
---
Engine/EffectInstance.cpp | 2 +-
Engine/Node.cpp | 36 +++++++++++++++++++++++++++++-------
Engine/Node.h | 2 +-
Engine/RotoContext.cpp | 15 +++++++++++++++
Engine/RotoContext.h | 2 ++
Engine/RotoPaint.cpp | 21 ++-------------------
6 files changed, 50 insertions(+), 28 deletions(-)
diff --git a/Engine/EffectInstance.cpp b/Engine/EffectInstance.cpp
index 5f7ef39376..2bcf840b5d 100644
--- a/Engine/EffectInstance.cpp
+++ b/Engine/EffectInstance.cpp
@@ -829,7 +829,7 @@ EffectInstance::getImage(int inputNb,
ImageBitDepthEnum depth;
n->getPreferredDepthAndComponents(-1, &prefComps, &depth);
assert(!prefComps.empty());
- qDebug() << n->getScriptName_mt_safe().c_str() << "output clip preferences is" << prefComps.front().getComponentsGlobalName().c_str();
+ qDebug() << n->getScriptName_mt_safe().c_str() << "output clip preference is" << prefComps.front().getComponentsGlobalName().c_str();
}
#endif
diff --git a/Engine/Node.cpp b/Engine/Node.cpp
index 095d3d1e65..bec476cd6a 100644
--- a/Engine/Node.cpp
+++ b/Engine/Node.cpp
@@ -3085,7 +3085,7 @@ Node::hasOutputNodesConnected(std::list* writers
{
Natron::OutputEffectInstance* thisWriter = dynamic_cast(_imp->liveInstance.get());
- if (thisWriter) {
+ if (thisWriter && thisWriter->isOutput()) {
std::list::const_iterator alreadyExists = std::find(writers->begin(), writers->end(), thisWriter);
if ( alreadyExists == writers->end() ) {
writers->push_back(thisWriter);
@@ -6720,7 +6720,7 @@ Node::forceRefreshAllInputRelatedData()
}
void
-Node::markInputRelatedDataDirtyRecursiveInternal(std::list& markedNodes) {
+Node::markInputRelatedDataDirtyRecursiveInternal(std::list& markedNodes,bool recurse) {
std::list::iterator found = std::find(markedNodes.begin(), markedNodes.end(), this);
if (found != markedNodes.end()) {
return;
@@ -6731,10 +6731,22 @@ Node::markInputRelatedDataDirtyRecursiveInternal(std::list& marke
}
markedNodes.push_back(this);
- std::list outputs;
- getOutputsWithGroupRedirection(outputs);
- for (std::list::const_iterator it = outputs.begin(); it != outputs.end(); ++it) {
- (*it)->markInputRelatedDataDirtyRecursiveInternal( markedNodes );
+ if (isRotoPaintingNode()) {
+ boost::shared_ptr roto = getRotoContext();
+ assert(roto);
+ std::list rotoNodes;
+ roto->getRotoPaintTreeNodes(&rotoNodes);
+ for (std::list::iterator it = rotoNodes.begin(); it!=rotoNodes.end(); ++it) {
+ (*it)->markInputRelatedDataDirtyRecursiveInternal(markedNodes,false);
+ }
+ }
+
+ if (recurse) {
+ std::list outputs;
+ getOutputsWithGroupRedirection(outputs);
+ for (std::list::const_iterator it = outputs.begin(); it != outputs.end(); ++it) {
+ (*it)->markInputRelatedDataDirtyRecursiveInternal( markedNodes, true );
+ }
}
@@ -6745,7 +6757,7 @@ void
Node::markInputRelatedDataDirtyRecursive()
{
std::list marked;
- markInputRelatedDataDirtyRecursiveInternal(marked);
+ markInputRelatedDataDirtyRecursiveInternal(marked, true);
}
void
@@ -6753,12 +6765,22 @@ Node::refreshInputRelatedDataRecursiveInternal(std::list& markedN
{
refreshInputRelatedDataInternal(markedNodes);
+ if (isRotoPaintingNode()) {
+ boost::shared_ptr roto = getRotoContext();
+ assert(roto);
+ boost::shared_ptr bottomMerge = roto->getRotoPaintBottomMergeNode();
+ if (bottomMerge) {
+ bottomMerge->refreshInputRelatedDataRecursiveInternal(markedNodes);
+ }
+ }
+
///Now notify outputs we have changed
std::list outputs;
getOutputsWithGroupRedirection(outputs);
for (std::list::const_iterator it = outputs.begin(); it != outputs.end(); ++it) {
(*it)->refreshInputRelatedDataRecursiveInternal( markedNodes );
}
+
}
void
diff --git a/Engine/Node.h b/Engine/Node.h
index f4a85c5a5b..cee881172d 100644
--- a/Engine/Node.h
+++ b/Engine/Node.h
@@ -1049,7 +1049,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
void markInputRelatedDataDirtyRecursive();
- void markInputRelatedDataDirtyRecursiveInternal(std::list& markedNodes);
+ void markInputRelatedDataDirtyRecursiveInternal(std::list& markedNodes,bool recurse);
bool refreshAllInputRelatedData(bool hasSerializationData,const std::vector >& inputs);
diff --git a/Engine/RotoContext.cpp b/Engine/RotoContext.cpp
index 55fff61594..f2811483b2 100644
--- a/Engine/RotoContext.cpp
+++ b/Engine/RotoContext.cpp
@@ -123,6 +123,21 @@ RotoContext::getStrokeBeingPainted() const
return _imp->strokeBeingPainted;
}
+boost::shared_ptr
+RotoContext::getRotoPaintBottomMergeNode() const
+{
+ std::list > items = getCurvesByRenderOrder();
+ if (items.empty()) {
+ return boost::shared_ptr();
+ }
+
+ const boost::shared_ptr& firstStrokeItem = items.back();
+ assert(firstStrokeItem);
+ boost::shared_ptr bottomMerge = firstStrokeItem->getMergeNode();
+ assert(bottomMerge);
+ return bottomMerge;
+}
+
void
RotoContext::getRotoPaintTreeNodes(std::list >* nodes) const
{
diff --git a/Engine/RotoContext.h b/Engine/RotoContext.h
index cd5d1b1497..0367e51973 100644
--- a/Engine/RotoContext.h
+++ b/Engine/RotoContext.h
@@ -376,6 +376,8 @@ class RotoContext
void getRotoPaintTreeNodes(std::list >* nodes) const;
+ boost::shared_ptr getRotoPaintBottomMergeNode() const;
+
void setStrokeBeingPainted(const boost::shared_ptr& stroke);
boost::shared_ptr getStrokeBeingPainted() const;
diff --git a/Engine/RotoPaint.cpp b/Engine/RotoPaint.cpp
index 644961a090..f04814c66f 100644
--- a/Engine/RotoPaint.cpp
+++ b/Engine/RotoPaint.cpp
@@ -223,15 +223,7 @@ FramesNeededMap
RotoPaint::getFramesNeeded(double time, int view)
{
boost::shared_ptr roto = getNode()->getRotoContext();
- std::list > items = roto->getCurvesByRenderOrder();
- if (items.empty()) {
- return FramesNeededMap();
- }
-
- const boost::shared_ptr& firstStrokeItem = items.back();
- assert(firstStrokeItem);
- boost::shared_ptr bottomMerge = firstStrokeItem->getMergeNode();
- assert(bottomMerge);
+ boost::shared_ptr bottomMerge = roto->getRotoPaintBottomMergeNode();
FramesNeededMap ret;
std::map > views;
@@ -251,16 +243,7 @@ RotoPaint::getRegionsOfInterest(double /*time*/,
RoIMap* ret)
{
boost::shared_ptr roto = getNode()->getRotoContext();
- std::list > items = roto->getCurvesByRenderOrder();
- if (items.empty()) {
- return;
- }
-
- const boost::shared_ptr& firstStrokeItem = items.back();
- assert(firstStrokeItem);
- boost::shared_ptr bottomMerge = firstStrokeItem->getMergeNode();
- assert(bottomMerge);
-
+ boost::shared_ptr bottomMerge = roto->getRotoPaintBottomMergeNode();
ret->insert(std::make_pair(bottomMerge->getLiveInstance(), renderWindow));
}
From 982a02f58c25881ca489a38c2e1f706510506f49 Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Tue, 29 Sep 2015 10:07:58 +0200
Subject: [PATCH 029/178] Fix #925
---
Engine/Node.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Engine/Node.cpp b/Engine/Node.cpp
index bec476cd6a..ac33173c47 100644
--- a/Engine/Node.cpp
+++ b/Engine/Node.cpp
@@ -2392,7 +2392,7 @@ Node::makeCacheInfo() const
std::string
Node::makeInfoForInput(int inputNumber) const
{
- if (inputNumber < 0 || inputNumber >= getMaxInputCount()) {
+ if (inputNumber < -1 || inputNumber >= getMaxInputCount()) {
return "";
}
const Natron::Node* inputNode = 0;
From 9aa1c2b443acc4e3f403b53bcfb2edaedc2ee1b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Devernay?=
Date: Tue, 29 Sep 2015 10:54:56 +0200
Subject: [PATCH 030/178] Viewer: fix labels/tooltips
---
Gui/ViewerTab.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gui/ViewerTab.cpp b/Gui/ViewerTab.cpp
index b8e7a25cc0..e68bb20ac9 100644
--- a/Gui/ViewerTab.cpp
+++ b/Gui/ViewerTab.cpp
@@ -680,7 +680,7 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
//QFont font(appFont,appFontSize);
- _imp->canEditFrameRangeLabel = new ClickableLabel(tr("Playback range"),_imp->playerButtonsContainer);
+ _imp->canEditFrameRangeLabel = new ClickableLabel(tr("Playback range:"),_imp->playerButtonsContainer);
//_imp->canEditFrameRangeLabel->setFont(font);
_imp->playerLayout->addWidget(_imp->canEditFrameRangeLabel);
@@ -734,7 +734,7 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
_imp->canEditFpsBox->setChecked(!_imp->fpsLocked);
QObject::connect( _imp->canEditFpsBox,SIGNAL( clicked(bool) ),this,SLOT( onCanSetFPSClicked(bool) ) );
- _imp->canEditFpsLabel = new ClickableLabel(tr("fps"),_imp->playerButtonsContainer);
+ _imp->canEditFpsLabel = new ClickableLabel(tr("fps:"),_imp->playerButtonsContainer);
QObject::connect(_imp->canEditFpsLabel, SIGNAL(clicked(bool)),this,SLOT(onCanSetFPSLabelClicked(bool)));
_imp->canEditFpsLabel->setToolTip(canEditFpsBoxTT);
//_imp->canEditFpsLabel->setFont(font);
@@ -748,7 +748,7 @@ ViewerTab::ViewerTab(const std::list & existingRotoNodes,
_imp->fpsBox->setValue(24.0);
_imp->fpsBox->setIncrement(0.1);
_imp->fpsBox->setToolTip( "" + tr("fps:") + "
" + tr(
- "Viewer playback framerate.") );
+ "Viewer playback framerate, in frames per second.") );
_imp->playerLayout->addWidget(_imp->fpsBox);
From 161a5fa4ae4423d47612478d738c656806bfe2f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Devernay?=
Date: Tue, 29 Sep 2015 11:52:55 +0200
Subject: [PATCH 031/178] TimeLineGui: mark TODOs for #917
---
Global/Enums.h | 2 ++
Gui/TimeLineGui.cpp | 51 ++++++++++++++++++++++++++++++++-------------
2 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/Global/Enums.h b/Global/Enums.h
index 6cd384c32a..bb8cee4092 100644
--- a/Global/Enums.h
+++ b/Global/Enums.h
@@ -37,6 +37,8 @@ enum TimelineStateEnum
eTimelineStateIdle,
eTimelineStateDraggingCursor,
eTimelineStateDraggingBoundary,
+ eTimelineStatePanning,
+ eTimelineStateSelectingRange,
};
enum TimelineChangeReasonEnum
diff --git a/Gui/TimeLineGui.cpp b/Gui/TimeLineGui.cpp
index 5b1c42a615..0a2723f091 100644
--- a/Gui/TimeLineGui.cpp
+++ b/Gui/TimeLineGui.cpp
@@ -670,24 +670,21 @@ TimeLineGui::seek(SequenceTime time)
void
TimeLineGui::mousePressEvent(QMouseEvent* e)
{
- int leftBound,rightBound;
- {
- QMutexLocker k(&_imp->boundariesMutex);
- leftBound = _imp->leftBoundary;
- rightBound = _imp->rightBoundary;
- }
if (buttonDownIsMiddle(e)) {
- centerOn(leftBound, rightBound);
-
- if (_imp->gui->isTripleSyncEnabled()) {
- _imp->updateEditorFrameRanges();
- _imp->updateOpenedViewersFrameRanges();
- }
+ _imp->state = eTimelineStatePanning;
+ } else if (buttonDownIsRight(e)) {
+ _imp->state = eTimelineStateSelectingRange;
} else {
_imp->lastMouseEventWidgetCoord = e->pos();
double t = toTimeLineCoordinates(e->x(),0).x();
SequenceTime tseq = std::floor(t + 0.5);
if (modCASIsControl(e)) {
+ int leftBound,rightBound;
+ {
+ QMutexLocker k(&_imp->boundariesMutex);
+ leftBound = _imp->leftBoundary;
+ rightBound = _imp->rightBoundary;
+ }
_imp->state = eTimelineStateDraggingBoundary;
int firstPos = toWidgetCoordinates(leftBound - 1,0).x();
int lastPos = toWidgetCoordinates(rightBound + 1,0).x();
@@ -720,7 +717,12 @@ TimeLineGui::mouseMoveEvent(QMouseEvent* e)
SequenceTime tseq = std::floor(t + 0.5);
bool distortViewPort = false;
bool onEditingFinishedOnly = appPTR->getCurrentSettings()->getRenderOnEditingFinishedOnly();
- if (_imp->state == eTimelineStateDraggingCursor && !onEditingFinishedOnly) {
+ if (_imp->state == eTimelineStatePanning) {
+#pragma message WARN("TODO: timeline panning")
+ } else if (_imp->state == eTimelineStateSelectingRange) {
+#pragma message WARN("TODO: timeline select range")
+ // https://github.com/MrKepzie/Natron/issues/917
+ } else if (_imp->state == eTimelineStateDraggingCursor && !onEditingFinishedOnly) {
if ( tseq != _imp->timeline->currentFrame() ) {
_imp->gui->setDraftRenderEnabled(true);
_imp->gui->getApp()->setLastViewerUsingTimeline(_imp->viewer->getNode());
@@ -783,8 +785,27 @@ TimeLineGui::leaveEvent(QEvent* e)
void
TimeLineGui::mouseReleaseEvent(QMouseEvent* e)
{
- if (_imp->state == eTimelineStateDraggingCursor) {
-
+ if (_imp->state == eTimelineStateSelectingRange) {
+#pragma message WARN("TODO: timeline select range")
+
+ // TODO: https://github.com/MrKepzie/Natron/issues/917
+ // - if the last selected frame is the same as the first selected frame, zoom on the PROJECT range (NOT the playback range as in the following)
+ // - if they are different, zoom on that range
+ int leftBound,rightBound;
+ {
+ QMutexLocker k(&_imp->boundariesMutex);
+ leftBound = _imp->leftBoundary;
+ rightBound = _imp->rightBoundary;
+ }
+
+ centerOn(leftBound, rightBound);
+
+ if (_imp->gui->isTripleSyncEnabled()) {
+ _imp->updateEditorFrameRanges();
+ _imp->updateOpenedViewersFrameRanges();
+ }
+ } else if (_imp->state == eTimelineStateDraggingCursor) {
+
bool wasScrubbing = false;
if (_imp->gui->isDraftRenderEnabled()) {
_imp->gui->setDraftRenderEnabled(false);
From ea67ff8f0fb77d67f9ec3a92facf37660a5eb34f Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Tue, 29 Sep 2015 12:02:37 +0200
Subject: [PATCH 032/178] Factorize image format conversions in renderRoI in
convertPlanesFormatsIfNeeded. Also fix several UI bugs
---
Engine/EffectInstance.cpp | 38 ++++++-----
Engine/EffectInstance.h | 8 +++
Engine/EffectInstanceRenderRoI.cpp | 100 ++++++++++++++++++++---------
Engine/Node.cpp | 5 +-
Engine/ViewerInstance.cpp | 2 +-
Gui/NodeGraph30.cpp | 24 ++++++-
Gui/ViewerGL.cpp | 8 ++-
7 files changed, 130 insertions(+), 55 deletions(-)
diff --git a/Engine/EffectInstance.cpp b/Engine/EffectInstance.cpp
index 2bcf840b5d..23fe844e8e 100644
--- a/Engine/EffectInstance.cpp
+++ b/Engine/EffectInstance.cpp
@@ -858,27 +858,21 @@ EffectInstance::getImage(int inputNb,
inputImg = rescaledImg;
}
-
-
- if ( comp.getNumComponents() != inputImg->getComponents().getNumComponents() ) {
- ImagePtr remappedImg;
- {
- Image::ReadAccess acc = inputImg->getReadRights();
-
- remappedImg.reset( new Image(comp, inputImg->getRoD(), inputImg->getBounds(), inputImg->getMipMapLevel(), inputImg->getPixelAspectRatio(), inputImg->getBitDepth(), false) );
-
- Natron::ViewerColorSpaceEnum colorspace = getApp()->getDefaultColorSpaceForBitDepth( inputImg->getBitDepth() );
- bool unPremultIfNeeded = getOutputPremultiplication() == eImagePremultiplicationPremultiplied &&
- inputImg->getComponents().getNumComponents() == 4 && comp.getNumComponents() == 3;
- inputImg->convertToFormat( inputImg->getBounds(),
- colorspace, colorspace,
- channelForMask, false, unPremultIfNeeded, remappedImg.get() );
- }
- inputImg = remappedImg;
+
+
+ //Remap if needed
+ ImagePremultiplicationEnum outputPremult;
+ if (comp.isColorPlane()) {
+ outputPremult = n->getOutputPremultiplication();
+ } else {
+ outputPremult = eImagePremultiplicationOpaque;
}
+
+ inputImg = convertPlanesFormatsIfNeeded(getApp(), inputImg, pixelRoI, comp, depth, getNode()->usesAlpha0ToConvertFromRGBToRGBA(), outputPremult);
-
- if ( inputImagesThreadLocal.empty() ) {
+
+
+ if (inputImagesThreadLocal.empty()) {
///If the effect is analysis (e.g: Tracker) there's no input images in the tread local storage, hence add it
_imp->addInputImageTempPointer(inputNb, inputImg);
}
@@ -3168,7 +3162,11 @@ EffectInstance::getFramesNeeded_public(U64 hash,
return framesNeeded;
}
- framesNeeded = getFramesNeeded(time, view);
+ try {
+ framesNeeded = getFramesNeeded(time, view);
+ } catch (std::exception &e) {
+ setPersistentMessage(Natron::eMessageTypeError, e.what());
+ }
_imp->actionsCache.setFramesNeededResult(hash, time, view, mipMapLevel, framesNeeded);
return framesNeeded;
diff --git a/Engine/EffectInstance.h b/Engine/EffectInstance.h
index 32c6ff4135..aa71e57efc 100644
--- a/Engine/EffectInstance.h
+++ b/Engine/EffectInstance.h
@@ -1661,6 +1661,14 @@ class EffectInstance
InputImagesMap *inputImages,
RoIMap* inputsRoI);
+ static boost::shared_ptr convertPlanesFormatsIfNeeded(const AppInstance* app,
+ const boost::shared_ptr& inputImage,
+ const RectI& roi,
+ const ImageComponents& targetComponents,
+ ImageBitDepthEnum targetDepth,
+ bool useAlpha0ForRGBToRGBAConversion,
+ ImagePremultiplicationEnum outputPremult);
+
/**
* @brief Called by getImage when the thread-storage was not set by the caller thread (mostly because this is a thread that is not
diff --git a/Engine/EffectInstanceRenderRoI.cpp b/Engine/EffectInstanceRenderRoI.cpp
index f194fab81f..ce173e440b 100644
--- a/Engine/EffectInstanceRenderRoI.cpp
+++ b/Engine/EffectInstanceRenderRoI.cpp
@@ -185,6 +185,46 @@ optimizeRectsToRender(Natron::EffectInstance* self,
}
} // optimizeRectsToRender
+ImagePtr
+EffectInstance::convertPlanesFormatsIfNeeded(const AppInstance* app,
+ const ImagePtr& inputImage,
+ const RectI& roi,
+ const ImageComponents& targetComponents,
+ ImageBitDepthEnum targetDepth,
+ bool useAlpha0ForRGBToRGBAConversion,
+ ImagePremultiplicationEnum outputPremult)
+{
+ bool imageConversionNeeded = targetComponents != inputImage->getComponents() || targetDepth != inputImage->getBitDepth();
+ if (!imageConversionNeeded) {
+ return inputImage;
+ } else {
+ /**
+ * Lock the downscaled image so it cannot be resized while creating the temp image and calling convertToFormat.
+ **/
+ Image::ReadAccess acc = inputImage->getReadRights();
+ RectI bounds = inputImage->getBounds();
+
+ ImagePtr tmp(new Image(targetComponents, inputImage->getRoD(), bounds, inputImage->getMipMapLevel(), inputImage->getPixelAspectRatio(), targetDepth, false));
+
+ bool unPremultIfNeeded = outputPremult == eImagePremultiplicationPremultiplied && inputImage->getComponentsCount() == 4 && tmp->getComponentsCount() == 3;
+
+ if (useAlpha0ForRGBToRGBAConversion) {
+ inputImage->convertToFormatAlpha0( roi,
+ app->getDefaultColorSpaceForBitDepth(inputImage->getBitDepth()),
+ app->getDefaultColorSpaceForBitDepth(targetDepth),
+ -1, false, unPremultIfNeeded, tmp.get() );
+ } else {
+ inputImage->convertToFormat( roi,
+ app->getDefaultColorSpaceForBitDepth(inputImage->getBitDepth()),
+ app->getDefaultColorSpaceForBitDepth(targetDepth),
+ -1, false, unPremultIfNeeded, tmp.get() );
+ }
+
+ return tmp;
+ }
+
+}
+
EffectInstance::RenderRoIRetCode
EffectInstance::renderRoI(const RenderRoIArgs & args,
ImageList* outputPlanes)
@@ -513,7 +553,33 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
- return inputEffectIdentity->renderRoI(inputArgs, outputPlanes);
+ RenderRoIRetCode ret = inputEffectIdentity->renderRoI(inputArgs, outputPlanes);
+ if (ret == eRenderRoIRetCodeOk) {
+ ImageList convertedPlanes;
+ AppInstance* app = getApp();
+ assert(inputArgs.components.size() == outputPlanes->size());
+ bool useAlpha0ForRGBToRGBAConversion = args.caller ? args.caller->getNode()->usesAlpha0ToConvertFromRGBToRGBA() : false;
+
+ std::list::const_iterator compIt = args.components.begin();
+
+ for (ImageList::iterator it = outputPlanes->begin(); it!=outputPlanes->end(); ++it,++compIt) {
+
+ ImagePremultiplicationEnum premult;
+ const ImageComponents & outComp = outputComponents.front();
+ if ( outComp.isColorPlane() ) {
+ premult = getOutputPremultiplication();
+ } else {
+ premult = eImagePremultiplicationOpaque;
+ }
+
+ ImagePtr tmp = convertPlanesFormatsIfNeeded(app, *it, args.roi, *compIt, inputArgs.bitdepth, useAlpha0ForRGBToRGBAConversion, premult);
+ assert(tmp);
+ convertedPlanes.push_back(tmp);
+ }
+ *outputPlanes = convertedPlanes;
+ } else {
+ return ret;
+ }
} else {
assert( outputPlanes->empty() );
}
@@ -1423,36 +1489,10 @@ EffectInstance::renderRoI(const RenderRoIArgs & args,
it->second.fullscaleImage->downscaleMipMap( it->second.fullscaleImage->getRoD(), roi, 0, args.mipMapLevel, false, it->second.downscaleImage.get() );
}
+
///The image might need to be converted to fit the original requested format
- bool imageConversionNeeded = it->first != it->second.downscaleImage->getComponents() || args.bitdepth != it->second.downscaleImage->getBitDepth();
-
- if ( imageConversionNeeded && (renderRetCode != eRenderRoIStatusRenderFailed) ) {
- /**
- * Lock the downscaled image so it cannot be resized while creating the temp image and calling convertToFormat.
- **/
- boost::shared_ptr tmp;
- {
- Image::ReadAccess acc = it->second.downscaleImage->getReadRights();
- RectI bounds = it->second.downscaleImage->getBounds();
-
- tmp.reset( new Image(it->first, it->second.downscaleImage->getRoD(), bounds, mipMapLevel, it->second.downscaleImage->getPixelAspectRatio(), args.bitdepth, false) );
-
- bool unPremultIfNeeded = planesToRender.outputPremult == eImagePremultiplicationPremultiplied && it->second.downscaleImage->getComponentsCount() == 4 && tmp->getComponentsCount() == 3;
-
- if (useAlpha0ForRGBToRGBAConversion) {
- it->second.downscaleImage->convertToFormatAlpha0( roi,
- getApp()->getDefaultColorSpaceForBitDepth( it->second.downscaleImage->getBitDepth() ),
- getApp()->getDefaultColorSpaceForBitDepth(args.bitdepth),
- -1, false, unPremultIfNeeded, tmp.get() );
- } else {
- it->second.downscaleImage->convertToFormat( roi,
- getApp()->getDefaultColorSpaceForBitDepth( it->second.downscaleImage->getBitDepth() ),
- getApp()->getDefaultColorSpaceForBitDepth(args.bitdepth),
- -1, false, unPremultIfNeeded, tmp.get() );
- }
- }
- it->second.downscaleImage = tmp;
- }
+ it->second.downscaleImage = convertPlanesFormatsIfNeeded(getApp(), it->second.downscaleImage, roi, it->first, args.bitdepth, useAlpha0ForRGBToRGBAConversion, planesToRender.outputPremult);
+
assert(it->second.downscaleImage->getComponents() == it->first && it->second.downscaleImage->getBitDepth() == args.bitdepth);
outputPlanes->push_back(it->second.downscaleImage);
}
diff --git a/Engine/Node.cpp b/Engine/Node.cpp
index ac33173c47..664a6304aa 100644
--- a/Engine/Node.cpp
+++ b/Engine/Node.cpp
@@ -5359,10 +5359,13 @@ Node::onInputChanged(int inputNb)
}
- if (!getApp()->getProject()->isLoadingProject() && !getApp()->isCreatingPythonGroup()) {
+
+ if ((!getApp()->getProject()->isLoadingProject() && !getApp()->isCreatingPythonGroup()) ||
+ _imp->liveInstance->isRotoPaintNode()) {
///When loading a group (or project) just wait until everything is setup to actually compute input
///related data such as clip preferences
+ ///Exception for the Rotopaint node which needs to setup its own graph internally
/**
* The plug-in might call getImage, set a valid thread storage on the tree.
diff --git a/Engine/ViewerInstance.cpp b/Engine/ViewerInstance.cpp
index 5c6ef46247..abb6a2ba81 100644
--- a/Engine/ViewerInstance.cpp
+++ b/Engine/ViewerInstance.cpp
@@ -604,7 +604,7 @@ ViewerInstance::renderViewer(int view,
}
- if ( (ret[0] == eStatusFailed) && (ret[1] == eStatusFailed) ) {
+ if ( (ret[0] == eStatusFailed) || (ret[1] == eStatusFailed) ) {
return eStatusFailed;
}
diff --git a/Gui/NodeGraph30.cpp b/Gui/NodeGraph30.cpp
index bf033943f7..4431101220 100644
--- a/Gui/NodeGraph30.cpp
+++ b/Gui/NodeGraph30.cpp
@@ -61,7 +61,27 @@ using namespace Natron;
void
NodeGraph::connectCurrentViewerToSelection(int inputNB)
{
- if ( !getLastSelectedViewer() ) {
+ ViewerTab* lastUsedViewer = getLastSelectedViewer();
+
+ if (lastUsedViewer) {
+ boost::shared_ptr collection = lastUsedViewer->getInternalNode()->getNode()->getGroup();
+ if (collection && collection->getNodeGraph() != this) {
+ //somehow the group doesn't belong to this nodegraph , pick another one
+ const std::list& tabs = getGui()->getViewersList();
+ lastUsedViewer = 0;
+ for (std::list::const_iterator it = tabs.begin(); it!=tabs.end(); ++it) {
+
+ boost::shared_ptr otherCollection = (*it)->getInternalNode()->getNode()->getGroup();
+ if (otherCollection && otherCollection->getNodeGraph() == this) {
+ lastUsedViewer = *it;
+ break;
+ }
+ }
+ }
+ }
+
+
+ if ( !lastUsedViewer ) {
_imp->_gui->getApp()->createNode( CreateNodeArgs(PLUGINID_NATRON_VIEWER,
"",
-1,-1,
@@ -76,7 +96,7 @@ NodeGraph::connectCurrentViewerToSelection(int inputNB)
}
///get a pointer to the last user selected viewer
- boost::shared_ptr v = boost::dynamic_pointer_cast( getLastSelectedViewer()->
+ boost::shared_ptr v = boost::dynamic_pointer_cast( lastUsedViewer->
getInternalNode()->getNode() );
///if the node is no longer active (i.e: it was deleted by the user), don't do anything.
diff --git a/Gui/ViewerGL.cpp b/Gui/ViewerGL.cpp
index ae254f2d4f..f26d64bfea 100644
--- a/Gui/ViewerGL.cpp
+++ b/Gui/ViewerGL.cpp
@@ -40,6 +40,7 @@ GCC_DIAG_UNUSED_PRIVATE_FIELD_OFF
#include
GCC_DIAG_UNUSED_PRIVATE_FIELD_ON
#include
+#include
#include "Engine/Lut.h"
#include "Engine/Node.h"
@@ -2861,6 +2862,10 @@ ViewerGL::enterEvent(QEvent* e)
// always running in the main thread
assert( qApp && qApp->thread() == QThread::currentThread() );
+ /*
+ We steal focus from all those widgets so that the user automatically
+ gets keyboard focus in viewer when mouse enters.
+ */
QWidget* currentFocus = qApp->focusWidget();
bool canSetFocus = !currentFocus ||
@@ -2872,7 +2877,8 @@ ViewerGL::enterEvent(QEvent* e)
currentFocus->objectName() == "Properties" ||
currentFocus->objectName() == "SettingsPanel" ||
currentFocus->objectName() == "qt_tabwidget_tabbar" ||
- currentFocus->objectName() == "PanelTabBar";
+ currentFocus->objectName() == "PanelTabBar" ||
+ dynamic_cast(currentFocus);
if (canSetFocus) {
setFocus();
From 7442410c7a2e006414d1ff72a3e3813dc1e12791 Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Tue, 29 Sep 2015 12:22:51 +0200
Subject: [PATCH 033/178] Missing refresh
---
Gui/GuiAppInstance.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Gui/GuiAppInstance.cpp b/Gui/GuiAppInstance.cpp
index 1cdb6e5dde..34595d9a9f 100644
--- a/Gui/GuiAppInstance.cpp
+++ b/Gui/GuiAppInstance.cpp
@@ -487,6 +487,13 @@ GuiAppInstance::createNodeGui(const boost::shared_ptr &node,
}
}
nodegui->getDagGui()->moveNodesForIdealPosition(nodegui,selectedNode,autoConnect);
+ if (autoConnect) {
+ std::list viewers;
+ node->hasViewersConnected(&viewers);
+ for (std::list::iterator it2 = viewers.begin(); it2 != viewers.end(); ++it2) {
+ (*it2)->renderCurrentFrame(true);
+ }
+ }
}
}
}
From fff0b5fdc471ba35f63935315b4c27b686289e66 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Devernay?=
Date: Tue, 29 Sep 2015 12:50:30 +0200
Subject: [PATCH 034/178] TimeLineGui: implement panning, see #917
---
Global/Enums.h | 2 +-
Gui/TimeLineGui.cpp | 137 +++++++++++++++++++++++++++++---------------
Gui/TimeLineGui.h | 4 +-
3 files changed, 94 insertions(+), 49 deletions(-)
diff --git a/Global/Enums.h b/Global/Enums.h
index bb8cee4092..311f344335 100644
--- a/Global/Enums.h
+++ b/Global/Enums.h
@@ -38,7 +38,7 @@ enum TimelineStateEnum
eTimelineStateDraggingCursor,
eTimelineStateDraggingBoundary,
eTimelineStatePanning,
- eTimelineStateSelectingRange,
+ eTimelineStateSelectingZoomRange,
};
enum TimelineChangeReasonEnum
diff --git a/Gui/TimeLineGui.cpp b/Gui/TimeLineGui.cpp
index 0a2723f091..7c0b4215f2 100644
--- a/Gui/TimeLineGui.cpp
+++ b/Gui/TimeLineGui.cpp
@@ -120,6 +120,8 @@ struct TimelineGuiPrivate
bool alphaCursor; // should cursor be drawn semi-transparant
QPoint lastMouseEventWidgetCoord;
Natron::TimelineStateEnum state; //state machine for mouse events
+ int mousePressX; // widget X coordinate of last click
+ int mouseMoveX; // widget X coordinate of last mousemove position
TimeLineZoomContext tlZoomCtx;
Natron::TextRenderer textRenderer;
QFont font;
@@ -144,6 +146,8 @@ struct TimelineGuiPrivate
, alphaCursor(false)
, lastMouseEventWidgetCoord()
, state(eTimelineStateIdle)
+ , mousePressX(0)
+ , mouseMoveX(0)
, tlZoomCtx()
, textRenderer()
, font(appFont,appFontSize)
@@ -159,7 +163,7 @@ struct TimelineGuiPrivate
void updateEditorFrameRanges()
{
- double zoomRight = parent->toTimeLineCoordinates(parent->width() - 1, 0).x();
+ double zoomRight = parent->toTimeLine(parent->width() - 1);
gui->getCurveEditor()->getCurveWidget()->centerOn(tlZoomCtx.left - 5, zoomRight - 5);
gui->getDopeSheetEditor()->centerOn(tlZoomCtx.left - 5, zoomRight - 5);
@@ -167,7 +171,7 @@ struct TimelineGuiPrivate
void updateOpenedViewersFrameRanges()
{
- double zoomRight = parent->toTimeLineCoordinates(parent->width() - 1, 0).x();
+ double zoomRight = parent->toTimeLine(parent->width() - 1);
const std::list &viewers = gui->getViewersList();
@@ -349,6 +353,12 @@ TimeLineGui::paintGL()
glCheckErrorIgnoreOSXBug();
glDisable(GL_SCISSOR_TEST);
+ if (_imp->state == eTimelineStateSelectingZoomRange) {
+#pragma message WARN("TODO: draw timeline select range")
+ // https://github.com/MrKepzie/Natron/issues/917
+ // draw the select range, from _imp->mousePressX to _imp->mouseMoveX
+ }
+
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -538,7 +548,7 @@ TimeLineGui::paintGL()
QString currentFrameStr( QString::number( _imp->timeline->currentFrame() ) );
double cursorTextXposWidget = cursorBtmWidgetCoord.x() - fontM.width(currentFrameStr) / 2.;
- double cursorTextPos = toTimeLineCoordinates(cursorTextXposWidget,0).x();
+ double cursorTextPos = toTimeLine(cursorTextXposWidget);
renderText(cursorTextPos,cursorTopLeft.y(), currentFrameStr, actualCursorColor, _imp->font);
glBegin(GL_POLYGON);
glVertex2f( cursorBtm.x(),cursorBtm.y() );
@@ -555,7 +565,7 @@ TimeLineGui::paintGL()
if ( leftBound != _imp->timeline->currentFrame() ) {
QString leftBoundStr( QString::number(leftBound) );
double leftBoundTextXposWidget = toWidgetCoordinates( ( leftBoundBtm.x() + leftBoundBtmRight.x() ) / 2.,0 ).x() - fontM.width(leftBoundStr) / 2.;
- double leftBoundTextPos = toTimeLineCoordinates(leftBoundTextXposWidget,0).x();
+ double leftBoundTextPos = toTimeLine(leftBoundTextXposWidget);
renderText(leftBoundTextPos,leftBoundTop.y(),
leftBoundStr, boundsColor, _imp->font);
}
@@ -570,7 +580,7 @@ TimeLineGui::paintGL()
if ( rightBound != cur ) {
QString rightBoundStr( QString::number( rightBound ) );
double rightBoundTextXposWidget = toWidgetCoordinates( ( rightBoundBtm.x() + rightBoundBtmLeft.x() ) / 2.,0 ).x() - fontM.width(rightBoundStr) / 2.;
- double rightBoundTextPos = toTimeLineCoordinates(rightBoundTextXposWidget,0).x();
+ double rightBoundTextPos = toTimeLine(rightBoundTextXposWidget);
renderText(rightBoundTextPos,rightBoundTop.y(),
rightBoundStr, boundsColor, _imp->font);
}
@@ -670,13 +680,15 @@ TimeLineGui::seek(SequenceTime time)
void
TimeLineGui::mousePressEvent(QMouseEvent* e)
{
+ _imp->mousePressX = e->x();
+ _imp->mouseMoveX = _imp->mousePressX;
if (buttonDownIsMiddle(e)) {
_imp->state = eTimelineStatePanning;
} else if (buttonDownIsRight(e)) {
- _imp->state = eTimelineStateSelectingRange;
+ _imp->state = eTimelineStateSelectingZoomRange;
} else {
_imp->lastMouseEventWidgetCoord = e->pos();
- double t = toTimeLineCoordinates(e->x(),0).x();
+ const double t = toTimeLine(_imp->mousePressX);
SequenceTime tseq = std::floor(t + 0.5);
if (modCASIsControl(e)) {
int leftBound,rightBound;
@@ -686,8 +698,8 @@ TimeLineGui::mousePressEvent(QMouseEvent* e)
rightBound = _imp->rightBoundary;
}
_imp->state = eTimelineStateDraggingBoundary;
- int firstPos = toWidgetCoordinates(leftBound - 1,0).x();
- int lastPos = toWidgetCoordinates(rightBound + 1,0).x();
+ int firstPos = toWidget(leftBound - 1);
+ int lastPos = toWidget(rightBound + 1);
int distFromFirst = std::abs(e->x() - firstPos);
int distFromLast = std::abs(e->x() - lastPos);
if (distFromFirst > distFromLast) {
@@ -705,23 +717,23 @@ TimeLineGui::mousePressEvent(QMouseEvent* e)
void
TimeLineGui::mouseMoveEvent(QMouseEvent* e)
{
- int leftBound,rightBound;
- {
- QMutexLocker k(&_imp->boundariesMutex);
- leftBound = _imp->leftBoundary;
- rightBound = _imp->rightBoundary;
- }
-
+ int mouseMoveXprev = _imp->mouseMoveX;
_imp->lastMouseEventWidgetCoord = e->pos();
- double t = toTimeLineCoordinates(e->x(),0).x();
+ _imp->mouseMoveX = e->x();
+ const double t = toTimeLine(_imp->mouseMoveX);
SequenceTime tseq = std::floor(t + 0.5);
bool distortViewPort = false;
bool onEditingFinishedOnly = appPTR->getCurrentSettings()->getRenderOnEditingFinishedOnly();
if (_imp->state == eTimelineStatePanning) {
-#pragma message WARN("TODO: timeline panning")
- } else if (_imp->state == eTimelineStateSelectingRange) {
-#pragma message WARN("TODO: timeline select range")
+ _imp->tlZoomCtx.left += toTimeLine(mouseMoveXprev) - toTimeLine(_imp->mouseMoveX);
+ update();
+ if (_imp->gui->isTripleSyncEnabled()) {
+ _imp->updateEditorFrameRanges();
+ _imp->updateOpenedViewersFrameRanges();
+ }
+ } else if (_imp->state == eTimelineStateSelectingZoomRange) {
// https://github.com/MrKepzie/Natron/issues/917
+ update();
} else if (_imp->state == eTimelineStateDraggingCursor && !onEditingFinishedOnly) {
if ( tseq != _imp->timeline->currentFrame() ) {
_imp->gui->setDraftRenderEnabled(true);
@@ -731,8 +743,14 @@ TimeLineGui::mouseMoveEvent(QMouseEvent* e)
distortViewPort = true;
_imp->alphaCursor = false;
} else if (_imp->state == eTimelineStateDraggingBoundary) {
- int firstPos = toWidgetCoordinates(leftBound - 1,0).x();
- int lastPos = toWidgetCoordinates(rightBound + 1,0).x();
+ int leftBound,rightBound;
+ {
+ QMutexLocker k(&_imp->boundariesMutex);
+ leftBound = _imp->leftBoundary;
+ rightBound = _imp->rightBoundary;
+ }
+ int firstPos = toWidget(leftBound - 1);
+ int lastPos = toWidget(rightBound + 1);
int distFromFirst = std::abs(e->x() - firstPos);
int distFromLast = std::abs(e->x() - lastPos);
if (distFromFirst > distFromLast) { // moving last frame anchor
@@ -752,8 +770,8 @@ TimeLineGui::mouseMoveEvent(QMouseEvent* e)
}
if (distortViewPort) {
- double leftMost = toTimeLineCoordinates(0,0).x();
- double rightMost = toTimeLineCoordinates(width() - 1,0).x();
+ double leftMost = toTimeLine(0);
+ double rightMost = toTimeLine(width() - 1);
if (tseq < leftMost) {
centerOn(tseq, rightMost);
} else if (tseq > rightMost) {
@@ -764,6 +782,7 @@ TimeLineGui::mouseMoveEvent(QMouseEvent* e)
} else {
update();
}
+
}
void
@@ -785,20 +804,29 @@ TimeLineGui::leaveEvent(QEvent* e)
void
TimeLineGui::mouseReleaseEvent(QMouseEvent* e)
{
- if (_imp->state == eTimelineStateSelectingRange) {
-#pragma message WARN("TODO: timeline select range")
-
- // TODO: https://github.com/MrKepzie/Natron/issues/917
- // - if the last selected frame is the same as the first selected frame, zoom on the PROJECT range (NOT the playback range as in the following)
+ if (_imp->state == eTimelineStateSelectingZoomRange) {
+ // - if the last selected frame is the same as the first selected frame, zoom on the PROJECT range
+ // (NOT the playback range as in the following, and NOT adding margins as centerOn() does)
// - if they are different, zoom on that range
- int leftBound,rightBound;
- {
- QMutexLocker k(&_imp->boundariesMutex);
- leftBound = _imp->leftBoundary;
- rightBound = _imp->rightBoundary;
+ double t = toTimeLine(e->x());
+
+ int leftBound = std::floor(t + 0.5);
+ int rightBound = std::floor(toTimeLine(_imp->mousePressX) + 0.5);
+ if (leftBound > rightBound) {
+ std::swap(leftBound, rightBound);
+ } else if (leftBound == rightBound) {
+ if (!_imp->viewerTab->isFileDialogViewer()) {
+ double firstFrame,lastFrame;
+ _imp->gui->getApp()->getFrameRange(&firstFrame, &lastFrame);
+ leftBound = std::floor(firstFrame + 0.5);
+ rightBound = std::floor(lastFrame + 0.5);
+
+ } else {
+ _imp->viewerTab->getTimelineBounds(&leftBound, &rightBound);
+ }
}
- centerOn(leftBound, rightBound);
+ centerOn(leftBound, rightBound, 0);
if (_imp->gui->isTripleSyncEnabled()) {
_imp->updateEditorFrameRanges();
@@ -819,7 +847,7 @@ TimeLineGui::mouseReleaseEvent(QMouseEvent* e)
if (onEditingFinishedOnly) {
- double t = toTimeLineCoordinates(e->x(),0).x();
+ double t = toTimeLine(e->x());
SequenceTime tseq = std::floor(t + 0.5);
if ( (tseq != _imp->timeline->currentFrame()) ) {
@@ -923,12 +951,13 @@ TimeLineGui::getVisibleRange(SequenceTime* left, SequenceTime* right) const
void
TimeLineGui::centerOn(SequenceTime left,
- SequenceTime right)
+ SequenceTime right,
+ int margin)
{
- double curveWidth = right - left + 10;
+ double curveWidth = right - left + 2 * margin;
double w = width();
- _imp->tlZoomCtx.left = left - 5;
+ _imp->tlZoomCtx.left = left - margin;
_imp->tlZoomCtx.zoomFactor = w / curveWidth;
update();
@@ -963,32 +992,46 @@ TimeLineGui::currentFrame() const
return _imp->timeline->currentFrame();
}
+double
+TimeLineGui::toTimeLine(double x) const
+{
+ double w = (double)width();
+ double left = _imp->tlZoomCtx.left;
+ double right = left + w / _imp->tlZoomCtx.zoomFactor;
+
+ return ( ( (right - left) * x ) / w ) + left;
+}
+
+double
+TimeLineGui::toWidget(double t) const
+{
+ double w = (double)width();
+ double left = _imp->tlZoomCtx.left;
+ double right = left + w / _imp->tlZoomCtx.zoomFactor;
+
+ return ( (t - left) / (right - left) ) * w;
+}
+
QPointF
TimeLineGui::toTimeLineCoordinates(double x,
double y) const
{
- double w = (double)width();
double h = (double)height();
double bottom = _imp->tlZoomCtx.bottom;
- double left = _imp->tlZoomCtx.left;
double top = bottom + h / _imp->tlZoomCtx.zoomFactor;
- double right = left + w / _imp->tlZoomCtx.zoomFactor;
- return QPointF( ( ( (right - left) * x ) / w ) + left,( ( (bottom - top) * y ) / h ) + top );
+ return QPointF( toTimeLine(x), ( ( (bottom - top) * y ) / h ) + top );
}
QPointF
TimeLineGui::toWidgetCoordinates(double x,
double y) const
{
- double w = (double)width();
double h = (double)height();
double bottom = _imp->tlZoomCtx.bottom;
- double left = _imp->tlZoomCtx.left;
double top = bottom + h / _imp->tlZoomCtx.zoomFactor;
- double right = left + w / _imp->tlZoomCtx.zoomFactor;
- return QPoint( ( (x - left) / (right - left) ) * w,( (y - top) / (bottom - top) ) * h );
+ return QPoint( toWidget(x), ( (y - top) / (bottom - top) ) * h );
}
void
diff --git a/Gui/TimeLineGui.h b/Gui/TimeLineGui.h
index 6688426fb7..75031dd0db 100644
--- a/Gui/TimeLineGui.h
+++ b/Gui/TimeLineGui.h
@@ -95,11 +95,13 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
*@brief See toZoomCoordinates in ViewerGL.h
**/
QPointF toTimeLineCoordinates(double x, double y) const;
+ double toTimeLine(double x) const;
/**
*@brief See toWidgetCoordinates in ViewerGL.h
**/
QPointF toWidgetCoordinates(double x, double y) const;
+ double toWidget(double t) const;
/**
* @brief Activates the SLOT onViewerCacheFrameAdded() and the SIGNALS removedLRUCachedFrame() and clearedViewerCache()
@@ -126,7 +128,7 @@ public Q_SLOTS:
void recenterOnBounds();
- void centerOn(SequenceTime left,SequenceTime right);
+ void centerOn(SequenceTime left, SequenceTime right, int margin = 5);
void onFrameChanged(SequenceTime,int);
From 1bc573cf3967b92342e017cca092d090cf0a23d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Devernay?=
Date: Tue, 29 Sep 2015 14:13:57 +0200
Subject: [PATCH 035/178] CurveWidgetPrivate: ignore OSX bug
---
Gui/CurveWidgetPrivate.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gui/CurveWidgetPrivate.cpp b/Gui/CurveWidgetPrivate.cpp
index 7f82fb9ec2..7b9a8a67ff 100644
--- a/Gui/CurveWidgetPrivate.cpp
+++ b/Gui/CurveWidgetPrivate.cpp
@@ -389,7 +389,7 @@ CurveWidgetPrivate::drawTimelineMarkers()
glVertex2f( _timeline->currentFrame(),btmRight.y() );
glVertex2f( _timeline->currentFrame(),topLeft.y() );
glEnd();
- glCheckError();
+ glCheckErrorIgnoreOSXBug();
glEnable(GL_POLYGON_SMOOTH);
glHint(GL_POLYGON_SMOOTH_HINT,GL_DONT_CARE);
@@ -401,7 +401,7 @@ CurveWidgetPrivate::drawTimelineMarkers()
glVertex2f( _timelineBtmPoly.at(1).x(),_timelineBtmPoly.at(1).y() );
glVertex2f( _timelineBtmPoly.at(2).x(),_timelineBtmPoly.at(2).y() );
glEnd();
- glCheckError();
+ glCheckErrorIgnoreOSXBug();
glBegin(GL_POLYGON);
glVertex2f( _timelineTopPoly.at(0).x(),_timelineTopPoly.at(0).y() );
@@ -409,7 +409,7 @@ CurveWidgetPrivate::drawTimelineMarkers()
glVertex2f( _timelineTopPoly.at(2).x(),_timelineTopPoly.at(2).y() );
glEnd();
} // GLProtectAttrib a(GL_HINT_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_POLYGON_BIT);
- glCheckError();
+ glCheckErrorIgnoreOSXBug();
}
void
From 21f6183617b22732cb5c060f510311fcdb32c144 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Devernay?=
Date: Tue, 29 Sep 2015 14:15:17 +0200
Subject: [PATCH 036/178] TimeLineGui: implement selection-based zooming
(right-click)
- right click on timeline: zoom back to project range
- right-click+drag: zoom on selected range
closes #917
see also #870
---
Gui/TimeLineGui.cpp | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/Gui/TimeLineGui.cpp b/Gui/TimeLineGui.cpp
index 7c0b4215f2..69865f444c 100644
--- a/Gui/TimeLineGui.cpp
+++ b/Gui/TimeLineGui.cpp
@@ -341,8 +341,8 @@ TimeLineGui::paintGL()
QPointF firstFrameWidgetPos = toWidgetCoordinates(firstFrame,0);
QPointF lastFrameWidgetPos = toWidgetCoordinates(lastFrame,0);
- glScissor( firstFrameWidgetPos.x(),0,
- lastFrameWidgetPos.x() - firstFrameWidgetPos.x(),height() );
+ glScissor( firstFrameWidgetPos.x(), 0,
+ lastFrameWidgetPos.x() - firstFrameWidgetPos.x(), height() );
double bgR,bgG,bgB;
settings->getBaseColor(&bgR, &bgG, &bgB);
@@ -353,14 +353,22 @@ TimeLineGui::paintGL()
glCheckErrorIgnoreOSXBug();
glDisable(GL_SCISSOR_TEST);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
if (_imp->state == eTimelineStateSelectingZoomRange) {
-#pragma message WARN("TODO: draw timeline select range")
+ // draw timeline selected range
// https://github.com/MrKepzie/Natron/issues/917
// draw the select range, from _imp->mousePressX to _imp->mouseMoveX
+ glColor4f(1, 1, 1, 0.3);
+ glBegin(GL_POLYGON);
+ glVertex2f(toTimeLine(_imp->mousePressX), btmLeft.y());
+ glVertex2f(toTimeLine(_imp->mousePressX), topRight.y());
+ glVertex2f(toTimeLine(_imp->mouseMoveX), topRight.y());
+ glVertex2f(toTimeLine(_imp->mouseMoveX), btmLeft.y());
+ glEnd();
}
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
QFontMetrics fontM(_imp->font);
From d2190e1d98ae37a42b3cba7495e874d3dd318034 Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Tue, 29 Sep 2015 15:02:48 +0200
Subject: [PATCH 037/178] Edition of connections in the graph can now be
enclosed in begin/end InputEdition. Also add InsertNodeCommand
---
Engine/Node.cpp | 89 ++++++++++-----
Engine/Node.h | 4 +
Engine/OfxEffectInstance.cpp | 10 +-
Gui/GuiAppInstance.cpp | 7 --
Gui/NodeGraph15.cpp | 29 +----
Gui/NodeGraphUndoRedo.cpp | 209 ++++++++++++++++++++++++++++-------
Gui/NodeGraphUndoRedo.h | 29 ++++-
7 files changed, 269 insertions(+), 108 deletions(-)
diff --git a/Engine/Node.cpp b/Engine/Node.cpp
index 664a6304aa..7a28df6e51 100644
--- a/Engine/Node.cpp
+++ b/Engine/Node.cpp
@@ -239,7 +239,6 @@ struct Node::Implementation
, childrenMutex()
, children()
, multiInstanceParentName()
- , duringInputChangedAction(false)
, keyframesDisplayedOnTimeline(false)
, timersMutex()
, lastRenderStartedSlotCallTime()
@@ -282,6 +281,8 @@ struct Node::Implementation
, distToNextOut(0.)
, useAlpha0ToConvertFromRGBToRGBA(false)
, isBeingDestroyed(false)
+ , inputModifiedRecursion(0)
+ , inputsModified()
{
///Initialize timers
gettimeofday(&lastRenderStartedSlotCallTime, 0);
@@ -442,7 +443,6 @@ struct Node::Implementation
///the name of the parent at the time this node was created
std::string multiInstanceParentName;
- bool duringInputChangedAction; //< true if we're during onInputChanged(...). MT-safe since only modified by the main thread
bool keyframesDisplayedOnTimeline;
///This is to avoid the slots connected to the main-thread to be called too much
@@ -505,6 +505,13 @@ struct Node::Implementation
bool isBeingDestroyed;
+ /*
+ Used to block render emitions while modifying nodes links
+ MT-safe: only accessed/used on main thread
+ */
+ int inputModifiedRecursion;
+ std::set inputsModified;
+
};
/**
@@ -3775,8 +3782,10 @@ Node::switchInput0And1()
Q_EMIT inputChanged(inputAIndex);
Q_EMIT inputChanged(inputBIndex);
if (!useGuiInputs) {
+ beginInputEdition();
onInputChanged(inputAIndex);
onInputChanged(inputBIndex);
+ endInputEdition(true);
}
computeHash();
@@ -5340,6 +5349,39 @@ Node::getImageBeingRendered(int time,
return boost::shared_ptr();
}
+void
+Node::beginInputEdition()
+{
+ assert( QThread::currentThread() == qApp->thread() );
+ ++_imp->inputModifiedRecursion;
+}
+
+void
+Node::endInputEdition(bool triggerRender)
+{
+ assert( QThread::currentThread() == qApp->thread() );
+ if (_imp->inputModifiedRecursion > 0) {
+ --_imp->inputModifiedRecursion;
+ }
+
+ if (!_imp->inputModifiedRecursion) {
+
+ forceRefreshAllInputRelatedData();
+ refreshDynamicProperties();
+
+ triggerRender = triggerRender && !_imp->inputsModified.empty();
+ _imp->inputsModified.clear();
+
+ if (triggerRender) {
+ std::list viewers;
+ hasViewersConnected(&viewers);
+ for (std::list::iterator it2 = viewers.begin(); it2 != viewers.end(); ++it2) {
+ (*it2)->renderCurrentFrame(true);
+ }
+ }
+ }
+}
+
void
Node::onInputChanged(int inputNb)
{
@@ -5347,21 +5389,24 @@ Node::onInputChanged(int inputNb)
return;
}
assert( QThread::currentThread() == qApp->thread() );
- _imp->duringInputChangedAction = true;
+
+ bool mustCallEndInputEdition = _imp->inputModifiedRecursion == 0;
+ if (mustCallEndInputEdition) {
+ beginInputEdition();
+ }
refreshMaskEnabledNess(inputNb);
refreshLayersChoiceSecretness(inputNb);
- refreshDynamicProperties();
ViewerInstance* isViewer = dynamic_cast(_imp->liveInstance.get());
if (isViewer) {
isViewer->refreshActiveInputs(inputNb);
}
+ bool shouldDoInputChanged = (!getApp()->getProject()->isLoadingProject() && !getApp()->isCreatingPythonGroup()) ||
+ _imp->liveInstance->isRotoPaintNode();
-
- if ((!getApp()->getProject()->isLoadingProject() && !getApp()->isCreatingPythonGroup()) ||
- _imp->liveInstance->isRotoPaintNode()) {
+ if (shouldDoInputChanged) {
///When loading a group (or project) just wait until everything is setup to actually compute input
///related data such as clip preferences
@@ -5390,21 +5435,23 @@ Node::onInputChanged(int inputNb)
///Don't do clip preferences while loading a project, they will be refreshed globally once the project is loaded.
-
_imp->liveInstance->onInputChanged(inputNb);
-
- forceRefreshAllInputRelatedData();
+ _imp->inputsModified.insert(inputNb);
+ }
+
+
+ if (mustCallEndInputEdition) {
+ endInputEdition(true);
}
- _imp->duringInputChangedAction = false;
}
void
Node::onParentMultiInstanceInputChanged(int input)
{
- _imp->duringInputChangedAction = true;
+ ++_imp->inputModifiedRecursion;
_imp->liveInstance->onInputChanged(input);
- _imp->duringInputChangedAction = false;
+ --_imp->inputModifiedRecursion;
}
@@ -5413,7 +5460,7 @@ Node::duringInputChangedAction() const
{
assert( QThread::currentThread() == qApp->thread() );
- return _imp->duringInputChangedAction;
+ return _imp->inputModifiedRecursion > 0;
}
void
@@ -6433,20 +6480,12 @@ Node::dequeueActions()
_imp->outputs = _imp->guiOutputs;
}
+ beginInputEdition();
for (std::set::iterator it = inputChanges.begin(); it!=inputChanges.end(); ++it) {
onInputChanged(*it);
}
-
- if (!inputChanges.empty()) {
- std::list viewers;
- hasViewersConnected(&viewers);
- for (std::list::iterator it = viewers.begin();
- it != viewers.end();
- ++it) {
- (*it)->renderCurrentFrame(true);
- }
- }
-
+ endInputEdition(true);
+
{
QMutexLocker k(&_imp->nodeIsDequeuingMutex);
_imp->nodeIsDequeuing = false;
diff --git a/Engine/Node.h b/Engine/Node.h
index cee881172d..88029fe8d6 100644
--- a/Engine/Node.h
+++ b/Engine/Node.h
@@ -790,6 +790,10 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
* do not respect the OpenFX specification.
**/
boost::shared_ptr getImageBeingRendered(int time,unsigned int mipMapLevel,int view);
+
+ void beginInputEdition();
+
+ void endInputEdition(bool triggerRender);
void onInputChanged(int inputNb);
diff --git a/Engine/OfxEffectInstance.cpp b/Engine/OfxEffectInstance.cpp
index 389d6bf387..31a470bb09 100644
--- a/Engine/OfxEffectInstance.cpp
+++ b/Engine/OfxEffectInstance.cpp
@@ -1669,7 +1669,7 @@ OfxEffectInstance::getFramesNeeded(double time, int view)
}
if ( (stat != kOfxStatOK) && (stat != kOfxStatReplyDefault) ) {
throw std::runtime_error("getFramesNeeded action failed");
- } else if (stat == kOfxStatOK) {
+ } else {
for (OFX::Host::ImageEffect::RangeMap::iterator it = inputRanges.begin(); it != inputRanges.end(); ++it) {
OfxClipInstance* clip = dynamic_cast(it->first);
assert(clip);
@@ -1684,9 +1684,11 @@ OfxEffectInstance::getFramesNeeded(double time, int view)
}
}
}
- if (stat == kOfxStatReplyDefault) {
- return Natron::EffectInstance::getFramesNeeded(time,view);
- }
+
+ //Default is already handled by HostSupport
+// if (stat == kOfxStatReplyDefault) {
+// return Natron::EffectInstance::getFramesNeeded(time,view);
+// }
return ret;
}
diff --git a/Gui/GuiAppInstance.cpp b/Gui/GuiAppInstance.cpp
index 34595d9a9f..1cdb6e5dde 100644
--- a/Gui/GuiAppInstance.cpp
+++ b/Gui/GuiAppInstance.cpp
@@ -487,13 +487,6 @@ GuiAppInstance::createNodeGui(const boost::shared_ptr &node,
}
}
nodegui->getDagGui()->moveNodesForIdealPosition(nodegui,selectedNode,autoConnect);
- if (autoConnect) {
- std::list viewers;
- node->hasViewersConnected(&viewers);
- for (std::list::iterator it2 = viewers.begin(); it2 != viewers.end(); ++it2) {
- (*it2)->renderCurrentFrame(true);
- }
- }
}
}
}
diff --git a/Gui/NodeGraph15.cpp b/Gui/NodeGraph15.cpp
index ddd47840e6..33c2227227 100644
--- a/Gui/NodeGraph15.cpp
+++ b/Gui/NodeGraph15.cpp
@@ -232,32 +232,9 @@ NodeGraph::mouseReleaseEvent(QMouseEvent* e)
_imp->_highLightedEdge->getSource() ) );
}
} else {
- boost::shared_ptr src = _imp->_highLightedEdge->getSource();
- pushUndoCommand( new ConnectCommand(this,_imp->_highLightedEdge,_imp->_highLightedEdge->getSource(),
- selectedNode) );
-
- ///find out if the node is already connected to what the edge is connected
- bool alreadyConnected = false;
- const std::vector > & inpNodes = selectedNode->getNode()->getGuiInputs();
- if (src) {
- for (U32 i = 0; i < inpNodes.size(); ++i) {
- if ( inpNodes[i] == src->getNode() ) {
- alreadyConnected = true;
- break;
- }
- }
- }
-
- if (src && !alreadyConnected) {
- ///push a second command... this is a bit dirty but I don't have time to add a whole new command just for this
- int prefInput = selectedNode->getNode()->getPreferredInputForConnection();
- if (prefInput != -1) {
- Edge* inputEdge = selectedNode->getInputArrow(prefInput);
- assert(inputEdge);
- pushUndoCommand( new ConnectCommand(this,inputEdge,inputEdge->getSource(),src) );
- }
- }
- }
+
+ pushUndoCommand(new InsertNodeCommand(this, _imp->_highLightedEdge, selectedNode));
+ } // if ( _imp->_highLightedEdge->isOutputEdge() )
_imp->_highLightedEdge = 0;
_imp->_hintInputEdge->hide();
diff --git a/Gui/NodeGraphUndoRedo.cpp b/Gui/NodeGraphUndoRedo.cpp
index 882f03f3b6..4c399a283e 100644
--- a/Gui/NodeGraphUndoRedo.cpp
+++ b/Gui/NodeGraphUndoRedo.cpp
@@ -410,96 +410,159 @@ ConnectCommand::ConnectCommand(NodeGraph* graph,
void
ConnectCommand::undo()
{
- doConnect(_newSrc.lock() ? _newSrc.lock()->getNode() : boost::shared_ptr(),
- _oldSrc.lock() ? _oldSrc.lock()->getNode() : boost::shared_ptr());
+ NodeGuiPtr newSrc = _newSrc.lock();
+ NodeGuiPtr oldSrc = _oldSrc.lock();
+ NodeGuiPtr dst = _dst.lock();
+ doConnect(newSrc,
+ oldSrc,
+ dst,
+ _inputNb);
+
+ if (newSrc) {
+ setText( QObject::tr("Connect %1 to %2")
+ .arg(dst->getNode()->getLabel().c_str() ).arg( newSrc->getNode()->getLabel().c_str() ) );
+ } else {
+ setText( QObject::tr("Disconnect %1")
+ .arg(dst->getNode()->getLabel().c_str() ) );
+ }
+
+
+ ViewerInstance* isDstAViewer = dynamic_cast(dst->getNode()->getLiveInstance() );
+ if (!isDstAViewer) {
+ _graph->getGui()->getApp()->triggerAutoSave();
+ }
+ _graph->update();
} // undo
void
ConnectCommand::redo()
{
- doConnect(_oldSrc.lock() ? _oldSrc.lock()->getNode() : boost::shared_ptr(),
- _newSrc.lock() ? _newSrc.lock()->getNode() : boost::shared_ptr());
-} // redo
-
-
-
-void
-ConnectCommand::doConnect(const boost::shared_ptr &oldSrc,
- const boost::shared_ptr & newSrc)
-{
+
+ NodeGuiPtr newSrc = _newSrc.lock();
+ NodeGuiPtr oldSrc = _oldSrc.lock();
NodeGuiPtr dst = _dst.lock();
- boost::shared_ptr internalDst = dst->getNode();
- InspectorNode* inspector = dynamic_cast(internalDst.get());
+ doConnect(oldSrc,
+ newSrc,
+ dst,
+ _inputNb);
if (newSrc) {
setText( QObject::tr("Connect %1 to %2")
- .arg(internalDst->getLabel().c_str() ).arg( newSrc->getLabel().c_str() ) );
+ .arg(dst->getNode()->getLabel().c_str() ).arg( newSrc->getNode()->getLabel().c_str() ) );
} else {
setText( QObject::tr("Disconnect %1")
- .arg(internalDst->getLabel().c_str() ) );
+ .arg(dst->getNode()->getLabel().c_str() ) );
}
+
+
+ ViewerInstance* isDstAViewer = dynamic_cast(dst->getNode()->getLiveInstance() );
+ if (!isDstAViewer) {
+ _graph->getGui()->getApp()->triggerAutoSave();
+ }
+ _graph->update();
+} // redo
+
+
+
+void
+ConnectCommand::doConnect(const NodeGuiPtr &oldSrc,
+ const NodeGuiPtr &newSrc,
+ const NodeGuiPtr& dst,
+ int inputNb)
+{
+ NodePtr internalDst = dst->getNode();
+ NodePtr internalNewSrc = newSrc ? newSrc->getNode() : NodePtr();
+ NodePtr internalOldSrc = oldSrc ? oldSrc->getNode() : NodePtr();
+
+ InspectorNode* inspector = dynamic_cast(internalDst.get());
+
+
if (inspector) {
///if the node is an inspector disconnect any current connection between the inspector and the _newSrc
for (int i = 0; i < inspector->getMaxInputCount(); ++i) {
- if (i != _inputNb && inspector->getInput(i) == newSrc) {
+ if (i != inputNb && inspector->getInput(i) == internalNewSrc) {
inspector->disconnectInput(i);
}
}
}
- if (oldSrc && newSrc) {
- internalDst->replaceInput(newSrc, _inputNb);
+ if (internalOldSrc && internalNewSrc) {
+ internalDst->replaceInput(internalNewSrc, inputNb);
} else {
- if (oldSrc && newSrc) {
- Natron::Node::CanConnectInputReturnValue ret = internalDst->canConnectInput(newSrc, _inputNb);
+ if (internalOldSrc && internalNewSrc) {
+ Natron::Node::CanConnectInputReturnValue ret = internalDst->canConnectInput(internalNewSrc, inputNb);
bool connectionOk = ret == Natron::Node::eCanConnectInput_ok ||
ret == Natron::Node::eCanConnectInput_differentFPS ||
ret == Natron::Node::eCanConnectInput_differentPars;
if (connectionOk) {
- internalDst->replaceInput(newSrc, _inputNb);
+ internalDst->replaceInput(internalNewSrc, inputNb);
} else {
- internalDst->disconnectInput(internalDst->getInputIndex(oldSrc.get()));
+ internalDst->disconnectInput(internalDst->getInputIndex(internalOldSrc.get()));
}
- } else if (oldSrc && !newSrc) {
- internalDst->disconnectInput(internalDst->getInputIndex(oldSrc.get()));
- } else if (!oldSrc && newSrc) {
- Natron::Node::CanConnectInputReturnValue ret = internalDst->canConnectInput(newSrc, _inputNb);
+ } else if (internalOldSrc && !internalNewSrc) {
+ internalDst->disconnectInput(internalDst->getInputIndex(internalOldSrc.get()));
+ } else if (!internalOldSrc && internalNewSrc) {
+ Natron::Node::CanConnectInputReturnValue ret = internalDst->canConnectInput(internalNewSrc, inputNb);
bool connectionOk = ret == Natron::Node::eCanConnectInput_ok ||
ret == Natron::Node::eCanConnectInput_differentFPS ||
ret == Natron::Node::eCanConnectInput_differentPars;
if (connectionOk) {
- internalDst->connectInput(newSrc,_inputNb);
+ internalDst->connectInput(internalNewSrc,inputNb);
} else {
- internalDst->disconnectInput(internalDst->getInputIndex(oldSrc.get()));
+ internalDst->disconnectInput(internalDst->getInputIndex(internalOldSrc.get()));
}
}
}
-
- assert(_dst.lock());
dst->refreshEdges();
dst->checkOptionalEdgesVisibility();
- boost::shared_ptr newSrcGui = _newSrc.lock();
- boost::shared_ptr oldSrcGui = _oldSrc.lock();
- if (newSrcGui) {
- newSrcGui->checkOptionalEdgesVisibility();
+
+ if (newSrc) {
+ newSrc->checkOptionalEdgesVisibility();
}
- if (oldSrcGui) {
- oldSrcGui->checkOptionalEdgesVisibility();
+ if (oldSrc) {
+ oldSrc->checkOptionalEdgesVisibility();
}
- ///if the node has no inputs, all the viewers attached to that node should be black.
- std::list viewers;
- internalDst->hasViewersConnected(&viewers);
- for (std::list::iterator it = viewers.begin(); it != viewers.end(); ++it) {
- (*it)->renderCurrentFrame(true);
+
+}
+
+InsertNodeCommand::InsertNodeCommand(NodeGraph* graph,
+ Edge* edge,
+ const boost::shared_ptr & newSrc,
+ QUndoCommand *parent)
+: ConnectCommand(graph,edge,edge->getSource(),newSrc,parent)
+, _inputEdge(0)
+{
+ assert(edge->getSource() && newSrc);
+ setText(QObject::tr("Insert node"));
+}
+
+
+void
+InsertNodeCommand::undo()
+{
+ NodeGuiPtr oldSrc = _oldSrc.lock();
+ NodeGuiPtr newSrc = _newSrc.lock();
+ NodeGuiPtr dst = _dst.lock();
+ assert(newSrc);
+
+ NodePtr oldSrcInternal = oldSrc ? oldSrc->getNode() : NodePtr();
+ NodePtr newSrcInternal = newSrc->getNode();
+ NodePtr dstInternal = dst->getNode();
+ assert(newSrcInternal && dstInternal);
+
+ doConnect(newSrc,oldSrc,dst,_inputNb);
+
+ if (_inputEdge) {
+ doConnect(_inputEdge->getSource(), NodeGuiPtr(), _inputEdge->getDest(), _inputEdge->getInputNumber());
}
- ViewerInstance* isDstAViewer = dynamic_cast(internalDst->getLiveInstance() );
+ ViewerInstance* isDstAViewer = dynamic_cast(dst->getNode()->getLiveInstance() );
if (!isDstAViewer) {
_graph->getGui()->getApp()->triggerAutoSave();
}
@@ -507,6 +570,66 @@ ConnectCommand::doConnect(const boost::shared_ptr &oldSrc,
}
+void
+InsertNodeCommand::redo()
+{
+ NodeGuiPtr oldSrc = _oldSrc.lock();
+ NodeGuiPtr newSrc = _newSrc.lock();
+ NodeGuiPtr dst = _dst.lock();
+ assert(newSrc);
+
+ NodePtr oldSrcInternal = oldSrc ? oldSrc->getNode() : NodePtr();
+ NodePtr newSrcInternal = newSrc->getNode();
+ NodePtr dstInternal = dst->getNode();
+ assert(newSrcInternal && dstInternal);
+
+ newSrcInternal->beginInputEdition();
+ dstInternal->beginInputEdition();
+
+ doConnect(oldSrc,newSrc,dst,_inputNb);
+
+
+ ///find out if the node is already connected to what the edge is connected
+ bool alreadyConnected = false;
+ const std::vector > & inpNodes = newSrcInternal->getGuiInputs();
+ if (oldSrcInternal) {
+ for (U32 i = 0; i < inpNodes.size(); ++i) {
+ if (inpNodes[i] == oldSrcInternal) {
+ alreadyConnected = true;
+ break;
+ }
+ }
+ }
+
+ _inputEdge = 0;
+ if (oldSrcInternal && !alreadyConnected) {
+ ///push a second command... this is a bit dirty but I don't have time to add a whole new command just for this
+ int prefInput = newSrcInternal->getPreferredInputForConnection();
+ if (prefInput != -1) {
+ _inputEdge = newSrc->getInputArrow(prefInput);
+ assert(_inputEdge);
+ doConnect(_inputEdge->getSource(), oldSrc, _inputEdge->getDest(), _inputEdge->getInputNumber());
+ }
+ }
+
+ ViewerInstance* isDstAViewer = dynamic_cast(dst->getNode()->getLiveInstance() );
+ if (!isDstAViewer) {
+ _graph->getGui()->getApp()->triggerAutoSave();
+ }
+
+ newSrcInternal->endInputEdition(false);
+ dstInternal->endInputEdition(false);
+
+ std::list viewers;
+ dstInternal->hasViewersConnected(&viewers);
+ for (std::list::iterator it2 = viewers.begin(); it2 != viewers.end(); ++it2) {
+ (*it2)->renderCurrentFrame(true);
+ }
+
+ _graph->update();
+
+}
+
ResizeBackDropCommand::ResizeBackDropCommand(const NodeGuiPtr& bd,
int w,
int h,
diff --git a/Gui/NodeGraphUndoRedo.h b/Gui/NodeGraphUndoRedo.h
index b78d2534ff..8037d61318 100644
--- a/Gui/NodeGraphUndoRedo.h
+++ b/Gui/NodeGraphUndoRedo.h
@@ -152,10 +152,12 @@ class ConnectCommand
virtual void undo();
virtual void redo();
-private:
+protected:
- void doConnect(const boost::shared_ptr &oldSrc,
- const boost::shared_ptr & newSrc);
+ static void doConnect(const NodeGuiPtr &oldSrc,
+ const NodeGuiPtr & newSrc,
+ const NodeGuiPtr& dst,
+ int inputNb);
boost::weak_ptr _oldSrc,_newSrc;
boost::weak_ptr _dst;
@@ -163,6 +165,27 @@ class ConnectCommand
int _inputNb;
};
+/*
+ * @brief Inserts an existing node in a stream
+ */
+class InsertNodeCommand : public ConnectCommand
+{
+public:
+
+ InsertNodeCommand(NodeGraph* graph,
+ Edge* edge,
+ const boost::shared_ptr & newSrc,
+ QUndoCommand *parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+
+ Edge* _inputEdge;
+
+};
+
class ResizeBackDropCommand
: public QUndoCommand
From 57f367c285f79b424d2a2ebaadf0ff92a71b25c4 Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Tue, 29 Sep 2015 15:14:11 +0200
Subject: [PATCH 038/178] Fix linux snapshots
---
tools/linux/README.md | 6 ++++++
tools/linux/snapshot.sh | 4 +++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/tools/linux/README.md b/tools/linux/README.md
index 4614c54652..f1e28e359e 100644
--- a/tools/linux/README.md
+++ b/tools/linux/README.md
@@ -78,7 +78,13 @@ For this to work you need to create a file named **repo.sh** next to *snapshot.s
REPO_DEST=user@host:/path
REPO_URL=http://some.url
+
+Launching snapshots
+===================
+ #Build GPL snapshots using 8 threads
+ MKJOBS=8 NATRON_LICENSE=GPL sh snapshot.sh
+
Release build:
===============
diff --git a/tools/linux/snapshot.sh b/tools/linux/snapshot.sh
index 755c9f2893..07ff63af4c 100644
--- a/tools/linux/snapshot.sh
+++ b/tools/linux/snapshot.sh
@@ -24,6 +24,8 @@
#Usage snapshot.sh noThreads
#Options:
#NO_LOOP=1: Only build once and then exits.
+#NATRON_LICENSE=(GPL,COMMERCIAL)
+#Usage example: MKJOBS=8 NATRON_LICENSE=GPL sh snapshot.sh
#Easier to debug
set -x
@@ -181,7 +183,7 @@ BUILD_CV=0
cd $CWD || exit 1
if [ "$FAIL" != "1" ]; then
if [ "$BUILD_NATRON" = "1" -o "$BUILD_IO" = "1" -o "$BUILD_MISC" = "1" -o "$BUILD_ARENA" = "1" -o "$BUILD_CV" = "1" ]; then
- NATRON_LICENSE=GPL OFFLINE_INSTALLER=1 SYNC=1 NOCLEAN=1 SNAPSHOT=1 sh build.sh workshop $JOBS
+ NATRON_LICENSE=$NATRON_LICENSE OFFLINE_INSTALLER=1 SYNC=1 NOCLEAN=1 SNAPSHOT=1 sh build.sh workshop $JOBS
fi
fi
From f40274dbb93edf8d6fd732ca3b2223d48aadeadd Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Tue, 29 Sep 2015 15:23:46 +0200
Subject: [PATCH 039/178] Viewerinstance: trigger render only if params changed
---
Engine/ViewerInstance.cpp | 96 +++++++++++++++++++++++++++------------
1 file changed, 67 insertions(+), 29 deletions(-)
diff --git a/Engine/ViewerInstance.cpp b/Engine/ViewerInstance.cpp
index abb6a2ba81..bd6d8a4928 100644
--- a/Engine/ViewerInstance.cpp
+++ b/Engine/ViewerInstance.cpp
@@ -2491,17 +2491,23 @@ ViewerInstance::onGammaChanged(double value)
{
// always running in the main thread
assert( qApp && qApp->thread() == QThread::currentThread() );
+ bool changed = false;
{
QMutexLocker l(&_imp->viewerParamsMutex);
- _imp->viewerParamsGamma = value;
- _imp->fillGammaLut(1. / value);
+ if (_imp->viewerParamsGamma != value) {
+ _imp->viewerParamsGamma = value;
+ _imp->fillGammaLut(1. / value);
+ changed = true;
+ }
}
assert(_imp->uiContext);
- if ( ( (_imp->uiContext->getBitDepth() == Natron::eImageBitDepthByte) || !_imp->uiContext->supportsGLSL() )
- && !getApp()->getProject()->isLoadingProject() ) {
- renderCurrentFrame(true);
- } else {
- _imp->uiContext->redraw();
+ if (changed) {
+ if ( ( (_imp->uiContext->getBitDepth() == Natron::eImageBitDepthByte) || !_imp->uiContext->supportsGLSL() )
+ && !getApp()->getProject()->isLoadingProject() ) {
+ renderCurrentFrame(true);
+ } else {
+ _imp->uiContext->redraw();
+ }
}
}
@@ -2517,17 +2523,23 @@ ViewerInstance::onGainChanged(double exp)
{
// always running in the main thread
assert( qApp && qApp->thread() == QThread::currentThread() );
-
+
+ bool changed = false;
{
QMutexLocker l(&_imp->viewerParamsMutex);
- _imp->viewerParamsGain = exp;
+ if (_imp->viewerParamsGain != exp) {
+ _imp->viewerParamsGain = exp;
+ changed = true;
+ }
}
- assert(_imp->uiContext);
- if ( ( (_imp->uiContext->getBitDepth() == Natron::eImageBitDepthByte) || !_imp->uiContext->supportsGLSL() )
- && !getApp()->getProject()->isLoadingProject() ) {
- renderCurrentFrame(true);
- } else {
- _imp->uiContext->redraw();
+ if (changed) {
+ assert(_imp->uiContext);
+ if ( ( (_imp->uiContext->getBitDepth() == Natron::eImageBitDepthByte) || !_imp->uiContext->supportsGLSL() )
+ && !getApp()->getProject()->isLoadingProject() ) {
+ renderCurrentFrame(true);
+ } else {
+ _imp->uiContext->redraw();
+ }
}
}
@@ -2554,12 +2566,15 @@ ViewerInstance::onAutoContrastChanged(bool autoContrast,
{
// always running in the main thread
assert( qApp && qApp->thread() == QThread::currentThread() );
-
+ bool changed = false;
{
QMutexLocker l(&_imp->viewerParamsMutex);
- _imp->viewerParamsAutoContrast = autoContrast;
+ if (_imp->viewerParamsAutoContrast != autoContrast) {
+ _imp->viewerParamsAutoContrast = autoContrast;
+ changed = true;
+ }
}
- if ( refresh && !getApp()->getProject()->isLoadingProject() ) {
+ if ( changed && refresh && !getApp()->getProject()->isLoadingProject() ) {
renderCurrentFrame(true);
}
}
@@ -2581,7 +2596,9 @@ ViewerInstance::onColorSpaceChanged(Natron::ViewerColorSpaceEnum colorspace)
{
QMutexLocker l(&_imp->viewerParamsMutex);
-
+ if (_imp->viewerParamsLut == colorspace) {
+ return;
+ }
_imp->viewerParamsLut = colorspace;
}
assert(_imp->uiContext);
@@ -2598,17 +2615,27 @@ ViewerInstance::setDisplayChannels(DisplayChannelsEnum channels, bool bothInputs
{
// always running in the main thread
assert( qApp && qApp->thread() == QThread::currentThread() );
-
+
+ bool changed = false;
{
QMutexLocker l(&_imp->viewerParamsMutex);
if (!bothInputs) {
- _imp->viewerParamsChannels[0] = channels;
+ if (_imp->viewerParamsChannels[0] != channels) {
+ _imp->viewerParamsChannels[0] = channels;
+ changed = true;
+ }
} else {
- _imp->viewerParamsChannels[0] = channels;
- _imp->viewerParamsChannels[1] = channels;
+ if (_imp->viewerParamsChannels[0] != channels) {
+ _imp->viewerParamsChannels[0] = channels;
+ changed = true;
+ }
+ if (_imp->viewerParamsChannels[1] != channels) {
+ _imp->viewerParamsChannels[1] = channels;
+ changed = true;
+ }
}
}
- if ( !getApp()->getProject()->isLoadingProject() ) {
+ if ( changed && !getApp()->getProject()->isLoadingProject() ) {
renderCurrentFrame(true);
}
}
@@ -2618,11 +2645,15 @@ ViewerInstance::setActiveLayer(const Natron::ImageComponents& layer, bool doRend
{
// always running in the main thread
assert( qApp && qApp->thread() == QThread::currentThread() );
+ bool changed = false;
{
QMutexLocker l(&_imp->viewerParamsMutex);
- _imp->viewerParamsLayer = layer;
+ if (_imp->viewerParamsLayer != layer) {
+ _imp->viewerParamsLayer = layer;
+ changed = true;
+ }
}
- if ( doRender && !getApp()->getProject()->isLoadingProject() ) {
+ if ( doRender && changed && !getApp()->getProject()->isLoadingProject() ) {
renderCurrentFrame(true);
}
}
@@ -2632,12 +2663,19 @@ ViewerInstance::setAlphaChannel(const Natron::ImageComponents& layer, const std:
{
// always running in the main thread
assert( qApp && qApp->thread() == QThread::currentThread() );
+ bool changed = false;
{
QMutexLocker l(&_imp->viewerParamsMutex);
- _imp->viewerParamsAlphaLayer = layer;
- _imp->viewerParamsAlphaChannelName = channelName;
+ if (_imp->viewerParamsAlphaLayer != layer) {
+ _imp->viewerParamsAlphaLayer = layer;
+ changed = true;
+ }
+ if (_imp->viewerParamsAlphaChannelName != channelName) {
+ _imp->viewerParamsAlphaChannelName = channelName;
+ changed = true;
+ }
}
- if ( doRender && !getApp()->getProject()->isLoadingProject() ) {
+ if ( changed && doRender && !getApp()->getProject()->isLoadingProject() ) {
renderCurrentFrame(true);
}
}
From e5bb8d4d257b3ff978ad8187ac0968f1967dc83d Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Tue, 29 Sep 2015 15:33:15 +0200
Subject: [PATCH 040/178] bug fix
---
Engine/Node.cpp | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/Engine/Node.cpp b/Engine/Node.cpp
index 7a28df6e51..00c8f07a47 100644
--- a/Engine/Node.cpp
+++ b/Engine/Node.cpp
@@ -4173,13 +4173,15 @@ Node::deactivate(const std::list< Node* > & outputsToDisconnect,
}
if (dc) {
int inputNb = (*it)->getInputIndex(this);
- _imp->deactivatedState.insert( make_pair(*it, inputNb) );
-
- ///reconnect if inputToConnectTo is not null
- if (inputToConnectTo) {
- (*it)->replaceInput(inputToConnectTo, inputNb);
- } else {
- ignore_result((*it)->disconnectInput(this));
+ if (inputNb != -1) {
+ _imp->deactivatedState.insert( make_pair(*it, inputNb) );
+
+ ///reconnect if inputToConnectTo is not null
+ if (inputToConnectTo) {
+ (*it)->replaceInput(inputToConnectTo, inputNb);
+ } else {
+ ignore_result((*it)->disconnectInput(this));
+ }
}
}
}
From 74c17015433cb903973326df2481c6f30b6073ab Mon Sep 17 00:00:00 2001
From: Alexandre Gauthier
Date: Tue, 29 Sep 2015 15:53:15 +0200
Subject: [PATCH 041/178] Python API: all getValueAtTime take double parameters
---
.../NatronEngine/BooleanParam.rst | 4 +-
.../NatronEngine/ChoiceParam.rst | 4 +-
.../NatronEngine/ColorParam.rst | 4 +-
.../NatronEngine/Double2DParam.rst | 1 +
.../NatronEngine/Double3DParam.rst | 1 +
.../NatronEngine/DoubleParam.rst | 4 +-
.../NatronEngine/Int2DParam.rst | 2 +-
.../NatronEngine/Int3DParam.rst | 2 +-
.../PythonReference/NatronEngine/IntParam.rst | 4 +-
.../NatronEngine/StringParamBase.rst | 4 +-
Engine/NatronEngine/booleanparam_wrapper.cpp | 26 +-
Engine/NatronEngine/choiceparam_wrapper.cpp | 26 +-
Engine/NatronEngine/colorparam_wrapper.cpp | 28 +-
Engine/NatronEngine/double2dparam_wrapper.cpp | 14 +-
Engine/NatronEngine/double3dparam_wrapper.cpp | 14 +-
Engine/NatronEngine/doubleparam_wrapper.cpp | 28 +-
Engine/NatronEngine/int2dparam_wrapper.cpp | 14 +-
Engine/NatronEngine/int3dparam_wrapper.cpp | 14 +-
Engine/NatronEngine/intparam_wrapper.cpp | 28 +-
.../natronengine_module_wrapper.cpp | 298 +++++++++---------
Engine/NatronEngine/natronengine_python.h | 92 +++---
.../NatronEngine/stringparambase_wrapper.cpp | 26 +-
Engine/ParameterWrapper.cpp | 32 +-
Engine/ParameterWrapper.h | 32 +-
Gui/EditExpressionDialog.cpp | 4 +-
Gui/NatronGui/natrongui_module_wrapper.cpp | 90 +++---
Gui/NatronGui/natrongui_python.h | 12 +-
27 files changed, 405 insertions(+), 403 deletions(-)
diff --git a/Documentation/source/PythonReference/NatronEngine/BooleanParam.rst b/Documentation/source/PythonReference/NatronEngine/BooleanParam.rst
index 3cb834c401..bfc601a5fa 100644
--- a/Documentation/source/PythonReference/NatronEngine/BooleanParam.rst
+++ b/Documentation/source/PythonReference/NatronEngine/BooleanParam.rst
@@ -53,7 +53,7 @@ Returns the value of the parameter at the current timeline's time.
.. method:: NatronEngine.BooleanParam.get(frame)
- :param frame: :class:`int`
+ :param frame: :class:`float`
:rtype: :class:`bool`
Returns the value of the parameter at the given *frame*. This value may be interpolated
@@ -85,7 +85,7 @@ Same as :func:`get()`
.. method:: NatronEngine.BooleanParam.getValueAtTime(time)
- :param time: :class:`int`
+ :param time: :class:`float`
:rtype: :class:`bool`
Same as :func:`get(frame)`
diff --git a/Documentation/source/PythonReference/NatronEngine/ChoiceParam.rst b/Documentation/source/PythonReference/NatronEngine/ChoiceParam.rst
index 9c38528148..69d80e4d50 100644
--- a/Documentation/source/PythonReference/NatronEngine/ChoiceParam.rst
+++ b/Documentation/source/PythonReference/NatronEngine/ChoiceParam.rst
@@ -67,7 +67,7 @@ hovers the entry with the mouse.
.. method:: NatronEngine.ChoiceParam.get(frame)
- :param frame: :class:`int`
+ :param frame: :class:`float`
:rtype: :class:`int`
Get the value of the parameter at the given *frame*.
@@ -130,7 +130,7 @@ Same as :func:`get()`
.. method:: NatronEngine.ChoiceParam.getValueAtTime(time)
- :param time: :class:`int`
+ :param time: :class:`float`
:rtype: :class:`int`
Same as :func:`get(frame)`
diff --git a/Documentation/source/PythonReference/NatronEngine/ColorParam.rst b/Documentation/source/PythonReference/NatronEngine/ColorParam.rst
index 1f1cb0462b..b507db9463 100644
--- a/Documentation/source/PythonReference/NatronEngine/ColorParam.rst
+++ b/Documentation/source/PythonReference/NatronEngine/ColorParam.rst
@@ -57,7 +57,7 @@ Member functions description
.. method:: NatronEngine.ColorParam.get(frame)
- :param frame: :class:`int`
+ :param frame: :class:`float`
:rtype: :class:`ColorTuple`
Returns a :doc:`ColorTuple` of the color held by the parameter at the given *frame*.
@@ -150,7 +150,7 @@ Returns the value of this parameter at the given *dimension* at the current time
.. method:: NatronEngine.ColorParam.getValueAtTime(time[, dimension=0])
- :param time: :class:`int`
+ :param time: :class:`float`
:param dimension: :class:`int`
:rtype: :class:`float`
diff --git a/Documentation/source/PythonReference/NatronEngine/Double2DParam.rst b/Documentation/source/PythonReference/NatronEngine/Double2DParam.rst
index 8bc5a53b60..38a42f7d36 100644
--- a/Documentation/source/PythonReference/NatronEngine/Double2DParam.rst
+++ b/Documentation/source/PythonReference/NatronEngine/Double2DParam.rst
@@ -48,6 +48,7 @@ timeline's time.
.. method:: NatronEngine.Double2DParam.get(frame)
+ :param frame: :class:`float`
:rtype: :class:`Double2DTuple`
Returns a :doc:`Double2DTuple` with the [x,y] values for this parameter at the given *frame*.
diff --git a/Documentation/source/PythonReference/NatronEngine/Double3DParam.rst b/Documentation/source/PythonReference/NatronEngine/Double3DParam.rst
index f8f9799f38..bfce69558f 100644
--- a/Documentation/source/PythonReference/NatronEngine/Double3DParam.rst
+++ b/Documentation/source/PythonReference/NatronEngine/Double3DParam.rst
@@ -34,6 +34,7 @@ timeline's time.
.. method:: NatronEngine.Double3DParam.get(frame)
+ :param frame: :class:`float`
:rtype: :class:`Double3DTuple`
Returns a :doc:`Double3DTuple` with the [x,y,z] values for this parameter at the given *frame*.
diff --git a/Documentation/source/PythonReference/NatronEngine/DoubleParam.rst b/Documentation/source/PythonReference/NatronEngine/DoubleParam.rst
index eca0ef7166..bb883bf319 100644
--- a/Documentation/source/PythonReference/NatronEngine/DoubleParam.rst
+++ b/Documentation/source/PythonReference/NatronEngine/DoubleParam.rst
@@ -69,7 +69,7 @@ Member functions description
.. method:: NatronEngine.DoubleParam.get(frame)
- :param frame: :class:`int`
+ :param frame: :class:`float`
:rtype: :class:`float`
Returns the value of this parameter at the given *frame*. If the animation curve has an
@@ -165,7 +165,7 @@ Returns the value of this parameter at the given *dimension* at the current time
.. method:: NatronEngine.DoubleParam.getValueAtTime(time[, dimension=0])
- :param time: :class:`int`
+ :param time: :class:`float`
:param dimension: :class:`int`
:rtype: :class:`float`
diff --git a/Documentation/source/PythonReference/NatronEngine/Int2DParam.rst b/Documentation/source/PythonReference/NatronEngine/Int2DParam.rst
index ed3cfe28a5..bf33b63278 100644
--- a/Documentation/source/PythonReference/NatronEngine/Int2DParam.rst
+++ b/Documentation/source/PythonReference/NatronEngine/Int2DParam.rst
@@ -36,7 +36,7 @@ current time.
.. method:: NatronEngine.Int2DParam.get(frame)
-
+ :param: :class:`float`
:rtype: :class: `Int2DTuple`
Returns a :doc:`Int2DTuple` containing the [x,y] value of this parameter at
diff --git a/Documentation/source/PythonReference/NatronEngine/Int3DParam.rst b/Documentation/source/PythonReference/NatronEngine/Int3DParam.rst
index 32e7cf59b2..cb0951f5fb 100644
--- a/Documentation/source/PythonReference/NatronEngine/Int3DParam.rst
+++ b/Documentation/source/PythonReference/NatronEngine/Int3DParam.rst
@@ -35,7 +35,7 @@ current time.
.. method:: NatronEngine.Int3DParam.get(frame)
- :param frame: :class:`int`
+ :param frame: :class:`float`
:rtype: :class:``
diff --git a/Documentation/source/PythonReference/NatronEngine/IntParam.rst b/Documentation/source/PythonReference/NatronEngine/IntParam.rst
index 7e22703848..383c88d8ac 100644
--- a/Documentation/source/PythonReference/NatronEngine/IntParam.rst
+++ b/Documentation/source/PythonReference/NatronEngine/IntParam.rst
@@ -71,7 +71,7 @@ Member functions description
.. method:: NatronEngine.IntParam.get(frame)
- :param frame: :class:`int`
+ :param frame: :class:`float`
:rtype: :class:`int`
@@ -173,7 +173,7 @@ Returns the value of this parameter at the given *dimension* at the current time
.. method:: NatronEngine.IntParam.getValueAtTime(time[, dimension=0])
- :param time: :class:`int`
+ :param time: :class:`float`
:param dimension: :class:`int`
:rtype: :class:`int`
diff --git a/Documentation/source/PythonReference/NatronEngine/StringParamBase.rst b/Documentation/source/PythonReference/NatronEngine/StringParamBase.rst
index 736d1496eb..60ec39c374 100644
--- a/Documentation/source/PythonReference/NatronEngine/StringParamBase.rst
+++ b/Documentation/source/PythonReference/NatronEngine/StringParamBase.rst
@@ -60,7 +60,7 @@ Get the value of the parameter at the current timeline's time
.. method:: NatronEngine.StringParamBase.get(frame)
- :param frame: :class:`int`
+ :param frame: :class:`float`
:rtype: :class:`str`
@@ -94,7 +94,7 @@ Same as :func:`get()`
.. method:: NatronEngine.StringParamBase.getValueAtTime(time)
- :param time: :class:`int`
+ :param time: :class:`float`
:rtype: :class:`str`
Same as :func:`get(frame)`
diff --git a/Engine/NatronEngine/booleanparam_wrapper.cpp b/Engine/NatronEngine/booleanparam_wrapper.cpp
index 4942c3083d..ecb31f0ba8 100644
--- a/Engine/NatronEngine/booleanparam_wrapper.cpp
+++ b/Engine/NatronEngine/booleanparam_wrapper.cpp
@@ -120,12 +120,12 @@ static PyObject* Sbk_BooleanParamFunc_get(PyObject* self, PyObject* args)
// Overloaded function decisor
// 0: get()const
- // 1: get(int)const
+ // 1: get(double)const
if (numArgs == 0) {
overloadId = 0; // get()const
} else if (numArgs == 1
- && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
- overloadId = 1; // get(int)const
+ && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ overloadId = 1; // get(double)const
}
// Function signature not found.
@@ -143,13 +143,13 @@ static PyObject* Sbk_BooleanParamFunc_get(PyObject* self, PyObject* args)
}
break;
}
- case 1: // get(int frame) const
+ case 1: // get(double frame) const
{
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
if (!PyErr_Occurred()) {
- // get(int)const
+ // get(double)const
bool cppResult = const_cast(cppSelf)->get(cppArg0);
pyResult = Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppResult);
}
@@ -164,7 +164,7 @@ static PyObject* Sbk_BooleanParamFunc_get(PyObject* self, PyObject* args)
return pyResult;
Sbk_BooleanParamFunc_get_TypeError:
- const char* overloads[] = {"", "int", 0};
+ const char* overloads[] = {"", "float", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.BooleanParam.get", overloads);
return 0;
}
@@ -234,9 +234,9 @@ static PyObject* Sbk_BooleanParamFunc_getValueAtTime(PyObject* self, PyObject* p
SBK_UNUSED(pythonToCpp)
// Overloaded function decisor
- // 0: getValueAtTime(int)const
- if ((pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArg)))) {
- overloadId = 0; // getValueAtTime(int)const
+ // 0: getValueAtTime(double)const
+ if ((pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArg)))) {
+ overloadId = 0; // getValueAtTime(double)const
}
// Function signature not found.
@@ -244,11 +244,11 @@ static PyObject* Sbk_BooleanParamFunc_getValueAtTime(PyObject* self, PyObject* p
// Call function/method
{
- int cppArg0;
+ double cppArg0;
pythonToCpp(pyArg, &cppArg0);
if (!PyErr_Occurred()) {
- // getValueAtTime(int)const
+ // getValueAtTime(double)const
bool cppResult = const_cast(cppSelf)->getValueAtTime(cppArg0);
pyResult = Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppResult);
}
@@ -261,7 +261,7 @@ static PyObject* Sbk_BooleanParamFunc_getValueAtTime(PyObject* self, PyObject* p
return pyResult;
Sbk_BooleanParamFunc_getValueAtTime_TypeError:
- const char* overloads[] = {"int", 0};
+ const char* overloads[] = {"float", 0};
Shiboken::setErrorAboutWrongArguments(pyArg, "NatronEngine.BooleanParam.getValueAtTime", overloads);
return 0;
}
diff --git a/Engine/NatronEngine/choiceparam_wrapper.cpp b/Engine/NatronEngine/choiceparam_wrapper.cpp
index c87055fe4b..25e68b8810 100644
--- a/Engine/NatronEngine/choiceparam_wrapper.cpp
+++ b/Engine/NatronEngine/choiceparam_wrapper.cpp
@@ -178,12 +178,12 @@ static PyObject* Sbk_ChoiceParamFunc_get(PyObject* self, PyObject* args)
// Overloaded function decisor
// 0: get()const
- // 1: get(int)const
+ // 1: get(double)const
if (numArgs == 0) {
overloadId = 0; // get()const
} else if (numArgs == 1
- && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
- overloadId = 1; // get(int)const
+ && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ overloadId = 1; // get(double)const
}
// Function signature not found.
@@ -201,13 +201,13 @@ static PyObject* Sbk_ChoiceParamFunc_get(PyObject* self, PyObject* args)
}
break;
}
- case 1: // get(int frame) const
+ case 1: // get(double frame) const
{
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
if (!PyErr_Occurred()) {
- // get(int)const
+ // get(double)const
int cppResult = const_cast(cppSelf)->get(cppArg0);
pyResult = Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppResult);
}
@@ -222,7 +222,7 @@ static PyObject* Sbk_ChoiceParamFunc_get(PyObject* self, PyObject* args)
return pyResult;
Sbk_ChoiceParamFunc_get_TypeError:
- const char* overloads[] = {"", "int", 0};
+ const char* overloads[] = {"", "float", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.ChoiceParam.get", overloads);
return 0;
}
@@ -389,9 +389,9 @@ static PyObject* Sbk_ChoiceParamFunc_getValueAtTime(PyObject* self, PyObject* py
SBK_UNUSED(pythonToCpp)
// Overloaded function decisor
- // 0: getValueAtTime(int)const
- if ((pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArg)))) {
- overloadId = 0; // getValueAtTime(int)const
+ // 0: getValueAtTime(double)const
+ if ((pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArg)))) {
+ overloadId = 0; // getValueAtTime(double)const
}
// Function signature not found.
@@ -399,11 +399,11 @@ static PyObject* Sbk_ChoiceParamFunc_getValueAtTime(PyObject* self, PyObject* py
// Call function/method
{
- int cppArg0;
+ double cppArg0;
pythonToCpp(pyArg, &cppArg0);
if (!PyErr_Occurred()) {
- // getValueAtTime(int)const
+ // getValueAtTime(double)const
int cppResult = const_cast(cppSelf)->getValueAtTime(cppArg0);
pyResult = Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppResult);
}
@@ -416,7 +416,7 @@ static PyObject* Sbk_ChoiceParamFunc_getValueAtTime(PyObject* self, PyObject* py
return pyResult;
Sbk_ChoiceParamFunc_getValueAtTime_TypeError:
- const char* overloads[] = {"int", 0};
+ const char* overloads[] = {"float", 0};
Shiboken::setErrorAboutWrongArguments(pyArg, "NatronEngine.ChoiceParam.getValueAtTime", overloads);
return 0;
}
diff --git a/Engine/NatronEngine/colorparam_wrapper.cpp b/Engine/NatronEngine/colorparam_wrapper.cpp
index f268b711de..b4b2d7aa84 100644
--- a/Engine/NatronEngine/colorparam_wrapper.cpp
+++ b/Engine/NatronEngine/colorparam_wrapper.cpp
@@ -120,12 +120,12 @@ static PyObject* Sbk_ColorParamFunc_get(PyObject* self, PyObject* args)
// Overloaded function decisor
// 0: get()const
- // 1: get(int)const
+ // 1: get(double)const
if (numArgs == 0) {
overloadId = 0; // get()const
} else if (numArgs == 1
- && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
- overloadId = 1; // get(int)const
+ && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ overloadId = 1; // get(double)const
}
// Function signature not found.
@@ -143,13 +143,13 @@ static PyObject* Sbk_ColorParamFunc_get(PyObject* self, PyObject* args)
}
break;
}
- case 1: // get(int frame) const
+ case 1: // get(double frame) const
{
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
if (!PyErr_Occurred()) {
- // get(int)const
+ // get(double)const
ColorTuple* cppResult = new ColorTuple(const_cast(cppSelf)->get(cppArg0));
pyResult = Shiboken::Object::newObject((SbkObjectType*)SbkNatronEngineTypes[SBK_COLORTUPLE_IDX], cppResult, true, true);
}
@@ -164,7 +164,7 @@ static PyObject* Sbk_ColorParamFunc_get(PyObject* self, PyObject* args)
return pyResult;
Sbk_ColorParamFunc_get_TypeError:
- const char* overloads[] = {"", "int", 0};
+ const char* overloads[] = {"", "float", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.ColorParam.get", overloads);
return 0;
}
@@ -572,12 +572,12 @@ static PyObject* Sbk_ColorParamFunc_getValueAtTime(PyObject* self, PyObject* arg
// Overloaded function decisor
- // 0: getValueAtTime(int,int)const
- if ((pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ // 0: getValueAtTime(double,int)const
+ if ((pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
if (numArgs == 1) {
- overloadId = 0; // getValueAtTime(int,int)const
+ overloadId = 0; // getValueAtTime(double,int)const
} else if ((pythonToCpp[1] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[1])))) {
- overloadId = 0; // getValueAtTime(int,int)const
+ overloadId = 0; // getValueAtTime(double,int)const
}
}
@@ -597,13 +597,13 @@ static PyObject* Sbk_ColorParamFunc_getValueAtTime(PyObject* self, PyObject* arg
goto Sbk_ColorParamFunc_getValueAtTime_TypeError;
}
}
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
int cppArg1 = 0;
if (pythonToCpp[1]) pythonToCpp[1](pyArgs[1], &cppArg1);
if (!PyErr_Occurred()) {
- // getValueAtTime(int,int)const
+ // getValueAtTime(double,int)const
double cppResult = const_cast(cppSelf)->getValueAtTime(cppArg0, cppArg1);
pyResult = Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppResult);
}
@@ -616,7 +616,7 @@ static PyObject* Sbk_ColorParamFunc_getValueAtTime(PyObject* self, PyObject* arg
return pyResult;
Sbk_ColorParamFunc_getValueAtTime_TypeError:
- const char* overloads[] = {"int, int = 0", 0};
+ const char* overloads[] = {"float, int = 0", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.ColorParam.getValueAtTime", overloads);
return 0;
}
diff --git a/Engine/NatronEngine/double2dparam_wrapper.cpp b/Engine/NatronEngine/double2dparam_wrapper.cpp
index 64285b1d43..c83a7dc908 100644
--- a/Engine/NatronEngine/double2dparam_wrapper.cpp
+++ b/Engine/NatronEngine/double2dparam_wrapper.cpp
@@ -57,12 +57,12 @@ static PyObject* Sbk_Double2DParamFunc_get(PyObject* self, PyObject* args)
// Overloaded function decisor
// 0: get()const
- // 1: get(int)const
+ // 1: get(double)const
if (numArgs == 0) {
overloadId = 0; // get()const
} else if (numArgs == 1
- && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
- overloadId = 1; // get(int)const
+ && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ overloadId = 1; // get(double)const
}
// Function signature not found.
@@ -80,13 +80,13 @@ static PyObject* Sbk_Double2DParamFunc_get(PyObject* self, PyObject* args)
}
break;
}
- case 1: // get(int frame) const
+ case 1: // get(double frame) const
{
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
if (!PyErr_Occurred()) {
- // get(int)const
+ // get(double)const
Double2DTuple* cppResult = new Double2DTuple(const_cast(cppSelf)->get(cppArg0));
pyResult = Shiboken::Object::newObject((SbkObjectType*)SbkNatronEngineTypes[SBK_DOUBLE2DTUPLE_IDX], cppResult, true, true);
}
@@ -101,7 +101,7 @@ static PyObject* Sbk_Double2DParamFunc_get(PyObject* self, PyObject* args)
return pyResult;
Sbk_Double2DParamFunc_get_TypeError:
- const char* overloads[] = {"", "int", 0};
+ const char* overloads[] = {"", "float", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.Double2DParam.get", overloads);
return 0;
}
diff --git a/Engine/NatronEngine/double3dparam_wrapper.cpp b/Engine/NatronEngine/double3dparam_wrapper.cpp
index 17d98441c2..964fd42bc4 100644
--- a/Engine/NatronEngine/double3dparam_wrapper.cpp
+++ b/Engine/NatronEngine/double3dparam_wrapper.cpp
@@ -57,12 +57,12 @@ static PyObject* Sbk_Double3DParamFunc_get(PyObject* self, PyObject* args)
// Overloaded function decisor
// 0: get()const
- // 1: get(int)const
+ // 1: get(double)const
if (numArgs == 0) {
overloadId = 0; // get()const
} else if (numArgs == 1
- && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
- overloadId = 1; // get(int)const
+ && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ overloadId = 1; // get(double)const
}
// Function signature not found.
@@ -80,13 +80,13 @@ static PyObject* Sbk_Double3DParamFunc_get(PyObject* self, PyObject* args)
}
break;
}
- case 1: // get(int frame) const
+ case 1: // get(double frame) const
{
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
if (!PyErr_Occurred()) {
- // get(int)const
+ // get(double)const
Double3DTuple* cppResult = new Double3DTuple(const_cast(cppSelf)->get(cppArg0));
pyResult = Shiboken::Object::newObject((SbkObjectType*)SbkNatronEngineTypes[SBK_DOUBLE3DTUPLE_IDX], cppResult, true, true);
}
@@ -101,7 +101,7 @@ static PyObject* Sbk_Double3DParamFunc_get(PyObject* self, PyObject* args)
return pyResult;
Sbk_Double3DParamFunc_get_TypeError:
- const char* overloads[] = {"", "int", 0};
+ const char* overloads[] = {"", "float", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.Double3DParam.get", overloads);
return 0;
}
diff --git a/Engine/NatronEngine/doubleparam_wrapper.cpp b/Engine/NatronEngine/doubleparam_wrapper.cpp
index d6e9cb04e0..03b3fd607a 100644
--- a/Engine/NatronEngine/doubleparam_wrapper.cpp
+++ b/Engine/NatronEngine/doubleparam_wrapper.cpp
@@ -120,12 +120,12 @@ static PyObject* Sbk_DoubleParamFunc_get(PyObject* self, PyObject* args)
// Overloaded function decisor
// 0: get()const
- // 1: get(int)const
+ // 1: get(double)const
if (numArgs == 0) {
overloadId = 0; // get()const
} else if (numArgs == 1
- && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
- overloadId = 1; // get(int)const
+ && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ overloadId = 1; // get(double)const
}
// Function signature not found.
@@ -143,13 +143,13 @@ static PyObject* Sbk_DoubleParamFunc_get(PyObject* self, PyObject* args)
}
break;
}
- case 1: // get(int frame) const
+ case 1: // get(double frame) const
{
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
if (!PyErr_Occurred()) {
- // get(int)const
+ // get(double)const
double cppResult = const_cast(cppSelf)->get(cppArg0);
pyResult = Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppResult);
}
@@ -164,7 +164,7 @@ static PyObject* Sbk_DoubleParamFunc_get(PyObject* self, PyObject* args)
return pyResult;
Sbk_DoubleParamFunc_get_TypeError:
- const char* overloads[] = {"", "int", 0};
+ const char* overloads[] = {"", "float", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.DoubleParam.get", overloads);
return 0;
}
@@ -572,12 +572,12 @@ static PyObject* Sbk_DoubleParamFunc_getValueAtTime(PyObject* self, PyObject* ar
// Overloaded function decisor
- // 0: getValueAtTime(int,int)const
- if ((pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ // 0: getValueAtTime(double,int)const
+ if ((pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
if (numArgs == 1) {
- overloadId = 0; // getValueAtTime(int,int)const
+ overloadId = 0; // getValueAtTime(double,int)const
} else if ((pythonToCpp[1] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[1])))) {
- overloadId = 0; // getValueAtTime(int,int)const
+ overloadId = 0; // getValueAtTime(double,int)const
}
}
@@ -597,13 +597,13 @@ static PyObject* Sbk_DoubleParamFunc_getValueAtTime(PyObject* self, PyObject* ar
goto Sbk_DoubleParamFunc_getValueAtTime_TypeError;
}
}
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
int cppArg1 = 0;
if (pythonToCpp[1]) pythonToCpp[1](pyArgs[1], &cppArg1);
if (!PyErr_Occurred()) {
- // getValueAtTime(int,int)const
+ // getValueAtTime(double,int)const
double cppResult = const_cast(cppSelf)->getValueAtTime(cppArg0, cppArg1);
pyResult = Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppResult);
}
@@ -616,7 +616,7 @@ static PyObject* Sbk_DoubleParamFunc_getValueAtTime(PyObject* self, PyObject* ar
return pyResult;
Sbk_DoubleParamFunc_getValueAtTime_TypeError:
- const char* overloads[] = {"int, int = 0", 0};
+ const char* overloads[] = {"float, int = 0", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.DoubleParam.getValueAtTime", overloads);
return 0;
}
diff --git a/Engine/NatronEngine/int2dparam_wrapper.cpp b/Engine/NatronEngine/int2dparam_wrapper.cpp
index 9d7d91bd3c..5f5a94bfe0 100644
--- a/Engine/NatronEngine/int2dparam_wrapper.cpp
+++ b/Engine/NatronEngine/int2dparam_wrapper.cpp
@@ -57,12 +57,12 @@ static PyObject* Sbk_Int2DParamFunc_get(PyObject* self, PyObject* args)
// Overloaded function decisor
// 0: get()const
- // 1: get(int)const
+ // 1: get(double)const
if (numArgs == 0) {
overloadId = 0; // get()const
} else if (numArgs == 1
- && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
- overloadId = 1; // get(int)const
+ && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ overloadId = 1; // get(double)const
}
// Function signature not found.
@@ -80,13 +80,13 @@ static PyObject* Sbk_Int2DParamFunc_get(PyObject* self, PyObject* args)
}
break;
}
- case 1: // get(int frame) const
+ case 1: // get(double frame) const
{
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
if (!PyErr_Occurred()) {
- // get(int)const
+ // get(double)const
Int2DTuple* cppResult = new Int2DTuple(const_cast(cppSelf)->get(cppArg0));
pyResult = Shiboken::Object::newObject((SbkObjectType*)SbkNatronEngineTypes[SBK_INT2DTUPLE_IDX], cppResult, true, true);
}
@@ -101,7 +101,7 @@ static PyObject* Sbk_Int2DParamFunc_get(PyObject* self, PyObject* args)
return pyResult;
Sbk_Int2DParamFunc_get_TypeError:
- const char* overloads[] = {"", "int", 0};
+ const char* overloads[] = {"", "float", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.Int2DParam.get", overloads);
return 0;
}
diff --git a/Engine/NatronEngine/int3dparam_wrapper.cpp b/Engine/NatronEngine/int3dparam_wrapper.cpp
index e1d146023e..020c98669b 100644
--- a/Engine/NatronEngine/int3dparam_wrapper.cpp
+++ b/Engine/NatronEngine/int3dparam_wrapper.cpp
@@ -57,12 +57,12 @@ static PyObject* Sbk_Int3DParamFunc_get(PyObject* self, PyObject* args)
// Overloaded function decisor
// 0: get()const
- // 1: get(int)const
+ // 1: get(double)const
if (numArgs == 0) {
overloadId = 0; // get()const
} else if (numArgs == 1
- && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
- overloadId = 1; // get(int)const
+ && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ overloadId = 1; // get(double)const
}
// Function signature not found.
@@ -80,13 +80,13 @@ static PyObject* Sbk_Int3DParamFunc_get(PyObject* self, PyObject* args)
}
break;
}
- case 1: // get(int frame) const
+ case 1: // get(double frame) const
{
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
if (!PyErr_Occurred()) {
- // get(int)const
+ // get(double)const
Int3DTuple* cppResult = new Int3DTuple(const_cast(cppSelf)->get(cppArg0));
pyResult = Shiboken::Object::newObject((SbkObjectType*)SbkNatronEngineTypes[SBK_INT3DTUPLE_IDX], cppResult, true, true);
}
@@ -101,7 +101,7 @@ static PyObject* Sbk_Int3DParamFunc_get(PyObject* self, PyObject* args)
return pyResult;
Sbk_Int3DParamFunc_get_TypeError:
- const char* overloads[] = {"", "int", 0};
+ const char* overloads[] = {"", "float", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.Int3DParam.get", overloads);
return 0;
}
diff --git a/Engine/NatronEngine/intparam_wrapper.cpp b/Engine/NatronEngine/intparam_wrapper.cpp
index a06e5b5468..52f6e20148 100644
--- a/Engine/NatronEngine/intparam_wrapper.cpp
+++ b/Engine/NatronEngine/intparam_wrapper.cpp
@@ -120,12 +120,12 @@ static PyObject* Sbk_IntParamFunc_get(PyObject* self, PyObject* args)
// Overloaded function decisor
// 0: get()const
- // 1: get(int)const
+ // 1: get(double)const
if (numArgs == 0) {
overloadId = 0; // get()const
} else if (numArgs == 1
- && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
- overloadId = 1; // get(int)const
+ && (pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ overloadId = 1; // get(double)const
}
// Function signature not found.
@@ -143,13 +143,13 @@ static PyObject* Sbk_IntParamFunc_get(PyObject* self, PyObject* args)
}
break;
}
- case 1: // get(int frame) const
+ case 1: // get(double frame) const
{
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
if (!PyErr_Occurred()) {
- // get(int)const
+ // get(double)const
int cppResult = const_cast(cppSelf)->get(cppArg0);
pyResult = Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppResult);
}
@@ -164,7 +164,7 @@ static PyObject* Sbk_IntParamFunc_get(PyObject* self, PyObject* args)
return pyResult;
Sbk_IntParamFunc_get_TypeError:
- const char* overloads[] = {"", "int", 0};
+ const char* overloads[] = {"", "float", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.IntParam.get", overloads);
return 0;
}
@@ -572,12 +572,12 @@ static PyObject* Sbk_IntParamFunc_getValueAtTime(PyObject* self, PyObject* args,
// Overloaded function decisor
- // 0: getValueAtTime(int,int)const
- if ((pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
+ // 0: getValueAtTime(double,int)const
+ if ((pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) {
if (numArgs == 1) {
- overloadId = 0; // getValueAtTime(int,int)const
+ overloadId = 0; // getValueAtTime(double,int)const
} else if ((pythonToCpp[1] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[1])))) {
- overloadId = 0; // getValueAtTime(int,int)const
+ overloadId = 0; // getValueAtTime(double,int)const
}
}
@@ -597,13 +597,13 @@ static PyObject* Sbk_IntParamFunc_getValueAtTime(PyObject* self, PyObject* args,
goto Sbk_IntParamFunc_getValueAtTime_TypeError;
}
}
- int cppArg0;
+ double cppArg0;
pythonToCpp[0](pyArgs[0], &cppArg0);
int cppArg1 = 0;
if (pythonToCpp[1]) pythonToCpp[1](pyArgs[1], &cppArg1);
if (!PyErr_Occurred()) {
- // getValueAtTime(int,int)const
+ // getValueAtTime(double,int)const
int cppResult = const_cast(cppSelf)->getValueAtTime(cppArg0, cppArg1);
pyResult = Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppResult);
}
@@ -616,7 +616,7 @@ static PyObject* Sbk_IntParamFunc_getValueAtTime(PyObject* self, PyObject* args,
return pyResult;
Sbk_IntParamFunc_getValueAtTime_TypeError:
- const char* overloads[] = {"int, int = 0", 0};
+ const char* overloads[] = {"float, int = 0", 0};
Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.IntParam.getValueAtTime", overloads);
return 0;
}
diff --git a/Engine/NatronEngine/natronengine_module_wrapper.cpp b/Engine/NatronEngine/natronengine_module_wrapper.cpp
index 874e4deb9c..a974769fa4 100644
--- a/Engine/NatronEngine/natronengine_module_wrapper.cpp
+++ b/Engine/NatronEngine/natronengine_module_wrapper.cpp
@@ -32,19 +32,16 @@ static PyMethodDef NatronEngine_methods[] = {
};
// Classes initialization functions ------------------------------------------------------------
-void init_RectD(PyObject* module);
-void init_PyCoreApplication(PyObject* module);
-void init_Group(PyObject* module);
-void init_App(PyObject* module);
-void init_AppSettings(PyObject* module);
-void init_ItemBase(PyObject* module);
-void init_Layer(PyObject* module);
-void init_BezierCurve(PyObject* module);
void init_Roto(PyObject* module);
void init_UserParamHolder(PyObject* module);
-void init_Effect(PyObject* module);
void init_Param(PyObject* module);
void init_AnimatedParam(PyObject* module);
+void init_IntParam(PyObject* module);
+void init_Int2DParam(PyObject* module);
+void init_Int3DParam(PyObject* module);
+void init_DoubleParam(PyObject* module);
+void init_Double2DParam(PyObject* module);
+void init_Double3DParam(PyObject* module);
void init_ColorParam(PyObject* module);
void init_ChoiceParam(PyObject* module);
void init_BooleanParam(PyObject* module);
@@ -53,22 +50,25 @@ void init_StringParam(PyObject* module);
void init_FileParam(PyObject* module);
void init_OutputFileParam(PyObject* module);
void init_PathParam(PyObject* module);
-void init_IntParam(PyObject* module);
-void init_Int2DParam(PyObject* module);
-void init_Int3DParam(PyObject* module);
-void init_DoubleParam(PyObject* module);
-void init_Double2DParam(PyObject* module);
-void init_Double3DParam(PyObject* module);
-void init_ButtonParam(PyObject* module);
-void init_GroupParam(PyObject* module);
void init_PageParam(PyObject* module);
+void init_ButtonParam(PyObject* module);
void init_ParametricParam(PyObject* module);
+void init_GroupParam(PyObject* module);
void init_Int2DTuple(PyObject* module);
void init_Int3DTuple(PyObject* module);
void init_Double2DTuple(PyObject* module);
void init_Double3DTuple(PyObject* module);
void init_ColorTuple(PyObject* module);
+void init_PyCoreApplication(PyObject* module);
+void init_Group(PyObject* module);
+void init_App(PyObject* module);
+void init_Effect(PyObject* module);
+void init_AppSettings(PyObject* module);
+void init_ItemBase(PyObject* module);
+void init_Layer(PyObject* module);
+void init_BezierCurve(PyObject* module);
void init_RectI(PyObject* module);
+void init_RectD(PyObject* module);
void init_Natron(PyObject* module);
// Required modules' type and converter arrays.
@@ -137,99 +137,6 @@ static PythonToCppFunc is_std_vector_RectI__PythonToCpp_std_vector_RectI__Conver
return 0;
}
-// C++ to Python conversion for type 'std::vector'.
-static PyObject* std_vector_std_string__CppToPython_std_vector_std_string_(const void* cppIn) {
- ::std::vector& cppInRef = *((::std::vector*)cppIn);
-
- // TEMPLATE - stdVectorToPyList - START
- ::std::vector::size_type vectorSize = cppInRef.size();
- PyObject* pyOut = PyList_New((int) vectorSize);
- for (::std::vector::size_type idx = 0; idx < vectorSize; ++idx) {
- ::std::string cppItem(cppInRef[idx]);
- PyList_SET_ITEM(pyOut, idx, Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppItem));
- }
- return pyOut;
- // TEMPLATE - stdVectorToPyList - END
-
-}
-static void std_vector_std_string__PythonToCpp_std_vector_std_string_(PyObject* pyIn, void* cppOut) {
- ::std::vector& cppOutRef = *((::std::vector*)cppOut);
-
- // TEMPLATE - pySeqToStdVector - START
- int vectorSize = PySequence_Size(pyIn);
- cppOutRef.reserve(vectorSize);
- for (int idx = 0; idx < vectorSize; ++idx) {
- Shiboken::AutoDecRef pyItem(PySequence_GetItem(pyIn, idx));
- ::std::string cppItem;
- Shiboken::Conversions::pythonToCppCopy(Shiboken::Conversions::PrimitiveTypeConverter(), pyItem, &(cppItem));
- cppOutRef.push_back(cppItem);
- }
- // TEMPLATE - pySeqToStdVector - END
-
-}
-static PythonToCppFunc is_std_vector_std_string__PythonToCpp_std_vector_std_string__Convertible(PyObject* pyIn) {
- if (Shiboken::Conversions::convertibleSequenceTypes(Shiboken::Conversions::PrimitiveTypeConverter(), pyIn))
- return std_vector_std_string__PythonToCpp_std_vector_std_string_;
- return 0;
-}
-
-// C++ to Python conversion for type 'std::pair'.
-static PyObject* std_pair_std_string_std_string__CppToPython_std_pair_std_string_std_string_(const void* cppIn) {
- ::std::pair& cppInRef = *((::std::pair*)cppIn);
-
- PyObject* pyOut = PyTuple_New(2);
- PyTuple_SET_ITEM(pyOut, 0, Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppInRef.first));
- PyTuple_SET_ITEM(pyOut, 1, Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppInRef.second));
- return pyOut;
-
-}
-static void std_pair_std_string_std_string__PythonToCpp_std_pair_std_string_std_string_(PyObject* pyIn, void* cppOut) {
- ::std::pair& cppOutRef = *((::std::pair*)cppOut);
-
- Shiboken::Conversions::pythonToCppCopy(Shiboken::Conversions::PrimitiveTypeConverter(), PySequence_Fast_GET_ITEM(pyIn, 0), &(cppOutRef.first));
- Shiboken::Conversions::pythonToCppCopy(Shiboken::Conversions::PrimitiveTypeConverter(), PySequence_Fast_GET_ITEM(pyIn, 1), &(cppOutRef.second));
-
-}
-static PythonToCppFunc is_std_pair_std_string_std_string__PythonToCpp_std_pair_std_string_std_string__Convertible(PyObject* pyIn) {
- if (Shiboken::Conversions::convertiblePairTypes(Shiboken::Conversions::PrimitiveTypeConverter(), false, Shiboken::Conversions::PrimitiveTypeConverter