diff --git a/.travis-coverity-scan-build.sh b/.travis-coverity-scan-build.sh index 183a7cf3ba..ba8a82d633 100755 --- a/.travis-coverity-scan-build.sh +++ b/.travis-coverity-scan-build.sh @@ -1,11 +1,17 @@ #!/bin/sh +# Modified coverity scan build script +# Original script available at https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh +# Additions (see corresponding sections below): +# - Verify Coverity Scan run condition +# - Verify Coverity Scan script test mode +# - set TOOL_BASE to a writable directory with more than 1Gb free space set -e # Environment check -echo -e "\033[33;1mNote: PROJECT_NAME and COVERITY_SCAN_TOKEN are available on Project Settings page on scan.coverity.com\033[0m" +echo -e "\033[33;1mNote: COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN are available on Project Settings page on scan.coverity.com\033[0m" [ -z "$COVERITY_SCAN_PROJECT_NAME" ] && echo "ERROR: COVERITY_SCAN_PROJECT_NAME must be set" && exit 1 -#[ -z "$COVERITY_SCAN_NOTIFICATION_EMAIL" ] && echo "ERROR: COVERITY_SCAN_NOTIFICATION_EMAIL must be set" && exit 1 +[ -z "$COVERITY_SCAN_NOTIFICATION_EMAIL" ] && echo "ERROR: COVERITY_SCAN_NOTIFICATION_EMAIL must be set" && exit 1 [ -z "$COVERITY_SCAN_BRANCH_PATTERN" ] && echo "ERROR: COVERITY_SCAN_BRANCH_PATTERN must be set" && exit 1 [ -z "$COVERITY_SCAN_BUILD_COMMAND" ] && echo "ERROR: COVERITY_SCAN_BUILD_COMMAND must be set" && exit 1 [ -z "$COVERITY_SCAN_TOKEN" ] && echo "ERROR: COVERITY_SCAN_TOKEN must be set" && exit 1 @@ -13,8 +19,9 @@ echo -e "\033[33;1mNote: PROJECT_NAME and COVERITY_SCAN_TOKEN are available on P PLATFORM=`uname` TOOL_ARCHIVE=/tmp/cov-analysis-${PLATFORM}.tgz TOOL_URL=https://scan.coverity.com/download/${PLATFORM} -TOOL_BASE=/tmp/coverity-scan-analysis -UPLOAD_URL="http://scan5.coverity.com/cgi-bin/travis_upload.py" +#TOOL_BASE=/tmp/coverity-scan-analysis +TOOL_BASE=/home/travis/coverity-scan-analysis +UPLOAD_URL="https://scan.coverity.com/builds" SCAN_URL="https://scan.coverity.com" # Verify Coverity Scan run condition @@ -54,7 +61,7 @@ else else WHEN=`echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['next_upload_permitted_at']"` echo -e "\033[33;1mCoverity Scan analysis NOT authorized until $WHEN.\033[0m" - exit 1 + exit 0 fi fi @@ -83,13 +90,13 @@ COV_BUILD_OPTIONS="" RESULTS_DIR="cov-int" eval "${COVERITY_SCAN_BUILD_COMMAND_PREPEND}" COVERITY_UNSUPPORTED=1 cov-build --dir $RESULTS_DIR $COV_BUILD_OPTIONS $COVERITY_SCAN_BUILD_COMMAND +cov-import-scm --dir $RESULTS_DIR --scm git --log $RESULTS_DIR/scm_log.txt 2>&1 # Upload results echo -e "\033[33;1mTarring Coverity Scan Analysis results...\033[0m" RESULTS_ARCHIVE=analysis-results.tgz tar czf $RESULTS_ARCHIVE $RESULTS_DIR SHA=`git rev-parse --short HEAD` -#VERSION_SHA=$(cat VERSION)#$SHA # Verify Coverity Scan script test mode if [ "$coverity_scan_script_test_mode" = true ]; then @@ -98,14 +105,18 @@ if [ "$coverity_scan_script_test_mode" = true ]; then fi echo -e "\033[33;1mUploading Coverity Scan Analysis results...\033[0m" -curl \ - --progress-bar \ +response=$(curl \ + --silent --write-out "\n%{http_code}\n" \ --form project=$COVERITY_SCAN_PROJECT_NAME \ --form token=$COVERITY_SCAN_TOKEN \ --form email=$COVERITY_SCAN_NOTIFICATION_EMAIL \ --form file=@$RESULTS_ARCHIVE \ --form version=$SHA \ --form description="Travis CI build" \ - $UPLOAD_URL - -# --form description="$VERSION_SHA" \ + $UPLOAD_URL) +status_code=$(echo "$response" | sed -n '$p') +if [ "$status_code" != "201" ]; then + TEXT=$(echo "$response" | sed '$d') + echo -e "\033[33;1mCoverity Scan upload failed: $TEXT.\033[0m" + exit 1 +fi diff --git a/BreakpadClient/BreakpadClient.pro b/BreakpadClient/BreakpadClient.pro index 9cf1632375..a19b74e7d3 100644 --- a/BreakpadClient/BreakpadClient.pro +++ b/BreakpadClient/BreakpadClient.pro @@ -64,7 +64,7 @@ unix { } # mac os x -mac { +macx { # hack to make minidump_generator.cc compile as it uses # esp instead of __esp # DEFINES += __DARWIN_UNIX03=0 -- looks like we do not need it anymore @@ -91,7 +91,7 @@ mac { } # linux -linux { +unix:!macx { SOURCES += \ $$BREAKPAD_PATH/client/linux/crash_generation/crash_generation_client.cc \ $$BREAKPAD_PATH/client/linux/crash_generation/crash_generation_server.cc \ @@ -105,7 +105,6 @@ linux { $$BREAKPAD_PATH/client/linux/minidump_writer/linux_dumper.cc \ $$BREAKPAD_PATH/client/linux/minidump_writer/linux_ptrace_dumper.cc \ $$BREAKPAD_PATH/client/linux/minidump_writer/minidump_writer.cc \ - $$BREAKPAD_PATH/client/linux/sender/google_crash_report_sender.cc \ $$BREAKPAD_PATH/common/linux/crc32.cc \ $$BREAKPAD_PATH/common/linux/dump_symbols.cc \ $$BREAKPAD_PATH/common/linux/elf_core_dump.cc \ diff --git a/Documentation/source/PythonReference/NatronEngine/Effect.rst b/Documentation/source/PythonReference/NatronEngine/Effect.rst index 0b845d3a0c..50f88ff1dc 100644 --- a/Documentation/source/PythonReference/NatronEngine/Effect.rst +++ b/Documentation/source/PythonReference/NatronEngine/Effect.rst @@ -46,6 +46,7 @@ Functions * def :meth:`setScriptName` (scriptName) * def :meth:`setSize` (w, h) * def :meth:`setSubGraphEditable` (editable) +* def :meth:`setPagesOrder` (pages) .. _details: @@ -489,3 +490,11 @@ The user will still be able to see the internal node graph but will not be able unlock it. +.. method:: NatronEngine.Effect.setPagesOrder(pages) + + :param pages: :class:`sequence` + +Given the string list *pages* try to find the corresponding pages by their-script name +and order them in the given order. + + diff --git a/Documentation/source/PythonReference/NatronEngine/Param.rst b/Documentation/source/PythonReference/NatronEngine/Param.rst index b8a4d86a3f..3d9d459ed4 100644 --- a/Documentation/source/PythonReference/NatronEngine/Param.rst +++ b/Documentation/source/PythonReference/NatronEngine/Param.rst @@ -37,10 +37,14 @@ Functions * def :meth:`setAddNewLine` (a) * def :meth:`setAnimationEnabled` (e) * def :meth:`setEnabled` (enabled[, dimension=0]) +* def :meth:`setEnabledByDefault` (enabled) * def :meth:`setEvaluateOnChange` (eval) * def :meth:`setHelp` (help) * def :meth:`setPersistant` (persistant) * def :meth:`setVisible` (visible) +* def :meth:`setVisibleByDefault` (visible) +* def :meth:`setAsAlias` (otherParam) + .. _details: @@ -447,7 +451,14 @@ When disabled, the parameter will be displayed in black and the user will not be to edit it. See :func:`getIsEnabled(dimension)` +.. method:: NatronEngine.Param.setEnabledByDefault(enabled) + + + :param enabled: :class:`bool` +Set whether the parameter should be enabled or not by default. +When disabled, the parameter will be displayed in black and the user will not be able +to edit it. .. method:: NatronEngine.Param.setEvaluateOnChange(eval) @@ -490,7 +501,27 @@ See :func:`getIsPersistant` Set whether this parameter should be visible or not to the user. See :func:`getIsVisible()` +.. method:: NatronEngine.Param.setVisibleByDefault(visible) + + + :param visible: :class:`bool` + +Set whether this parameter should be visible or not to the user in its default state. + + +.. method:: NatronEngine.StringParamBase.setAsAlias(otherParam) + + :param otherParam: :class:`Param` + :rtype: :class:`bool` + + +Set this parameter as an alias of *otherParam*. +They need to be both of the same *type* and of the same *dimension*. +This parameter will control *otherParam* entirely and in case of a choice param, its +drop-down menu will be updated whenever the *otherParam* menu is updated. +This is used generally to make user parameters on groups with the "Pick" option of the +"Manage User Parameters" dialog. diff --git a/Engine/AppInstance.cpp b/Engine/AppInstance.cpp index 6061aed682..8912a29dea 100644 --- a/Engine/AppInstance.cpp +++ b/Engine/AppInstance.cpp @@ -29,6 +29,7 @@ #include #include +#include #include // QtCore on Qt4, QtConcurrent on Qt5 #include #include @@ -685,8 +686,12 @@ AppInstance::createNodeFromPythonModule(Natron::Plugin* plugin, group); containerNode = createNode(groupArgs); std::string containerName; - group->initNodeName(plugin->getLabelWithoutSuffix().toStdString(),&containerName); - containerNode->setScriptName(containerName); + try { + group->initNodeName(plugin->getLabelWithoutSuffix().toStdString(),&containerName); + containerNode->setScriptName(containerName); + } catch (...) { + + } } else { @@ -1013,7 +1018,11 @@ AppInstance::createNodeInternal(const QString & pluginID, CreateNodeArgs::DefaultValuesList(), isGrp); output = createNode(args); - output->setScriptName("Output"); + try { + output->setScriptName("Output"); + } catch (...) { + + } assert(output); } { @@ -1510,9 +1519,9 @@ AppInstance::save(const std::string& filename) { boost::shared_ptr project= getProject(); if (project->hasProjectBeenSavedByUser()) { - QString projectName = project->getProjectName(); + QString projectFilename = project->getProjectFilename(); QString projectPath = project->getProjectPath(); - return project->saveProject(projectPath, projectName, 0); + return project->saveProject(projectPath, projectFilename, 0); } else { return saveAs(filename); } diff --git a/Engine/AppInstance.h b/Engine/AppInstance.h index bddaef4623..83fd967907 100644 --- a/Engine/AppInstance.h +++ b/Engine/AppInstance.h @@ -36,11 +36,9 @@ #include #include "Global/GlobalDefines.h" +#include "Engine/RectD.h" #include "Engine/EngineFwd.h" -class QFileInfo; -class QMutex; - struct AppInstancePrivate; struct CreateNodeArgs @@ -377,8 +375,13 @@ class AppInstance virtual bool isDraftRenderEnabled() const { return false; } - virtual void setUserIsPainting(const boost::shared_ptr& /*rotopaintNode*/) {} - virtual boost::shared_ptr getIsUserPainting() const { return boost::shared_ptr(); } + virtual void setUserIsPainting(const boost::shared_ptr& /*rotopaintNode*/, + const boost::shared_ptr& /*stroke*/, + bool /*isPainting*/) {} + + virtual void getActiveRotoDrawingStroke(boost::shared_ptr* /*node*/, + boost::shared_ptr* /*stroke*/, + bool* /*isPainting*/) const { } virtual bool isRenderStatsActionChecked() const { return false; } @@ -398,6 +401,22 @@ class AppInstance virtual void* getOfxHostOSHandle() const { return NULL; } + virtual void updateLastPaintStrokeData(int /*newAge*/, + const std::list >& /*points*/, + const RectD& /*lastPointsBbox*/, + int /*strokeIndex*/) {} + + virtual void getLastPaintStrokePoints(std::list > >* /*strokes*/, int* /*strokeIndex*/) const {} + + virtual int getStrokeLastIndex() const { return -1; } + + virtual void getRenderStrokeData(RectD* /*lastStrokeMovementBbox*/, std::list >* /*lastStrokeMovementPoints*/, + double */*distNextIn*/, boost::shared_ptr* /*strokeImage*/) const {} + + virtual void updateStrokeImage(const boost::shared_ptr& /*image*/, double /*distNextOut*/, bool /*setDistNextOut*/) {} + + virtual RectD getLastPaintStrokeBbox() const { return RectD(); } + public Q_SLOTS: void quit(); diff --git a/Engine/AppManager.cpp b/Engine/AppManager.cpp index 1ebe9d4937..e237d38b8f 100644 --- a/Engine/AppManager.cpp +++ b/Engine/AppManager.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -75,6 +76,7 @@ #include "Engine/Project.h" #include "Engine/RotoPaint.h" #include "Engine/RotoSmear.h" +#include "Engine/StandardPaths.h" #include "Engine/ViewerInstance.h" // RenderStatsMap @@ -2616,7 +2618,7 @@ AppManager::isProjectAlreadyOpened(const std::string& projectFilePath) const boost::shared_ptr proj = it->second.app->getProject(); if (proj) { QString path = proj->getProjectPath(); - QString name = proj->getProjectName(); + QString name = proj->getProjectFilename(); std::string existingProject = path.toStdString() + name.toStdString(); if (existingProject == projectFilePath) { return it->first; @@ -2643,17 +2645,29 @@ AppManager::onCrashReporterOutputWritten() //At this point, the CrashReporter just notified us it is ready, so we can create our exception handler safely //because we know the pipe is opened on the other side. + QString dumpPath = Natron::StandardPaths::writableLocation(Natron::StandardPaths::eStandardLocationTemp); + #if defined(Q_OS_MAC) - _imp->breakpadHandler.reset(new google_breakpad::ExceptionHandler( std::string(), 0, 0/*dmpcb*/, 0, true, + _imp->breakpadHandler.reset(new google_breakpad::ExceptionHandler( dumpPath.toStdString(), + 0, + 0/*dmpcb*/, + 0, + true, _imp->crashReporterBreakpadPipe.toStdString().c_str())); #elif defined(Q_OS_LINUX) - _imp->breakpadHandler.reset(new google_breakpad::ExceptionHandler( google_breakpad::MinidumpDescriptor(std::string()), 0, 0/*dmpCb*/, - 0, true, handle)); + _imp->breakpadHandler.reset(new google_breakpad::ExceptionHandler( google_breakpad::MinidumpDescriptor(dumpPath.toStdString()), + 0, + 0/*dmpCb*/, + 0, + true, + _imp->crashReporterBreakpadPipe.handle())); #elif defined(Q_OS_WIN32) - _imp->breakpadHandler.reset(new google_breakpad::ExceptionHandler( std::wstring(), 0, 0/*dmpcb*/, + _imp->breakpadHandler.reset(new google_breakpad::ExceptionHandler( dumpPath.toStdWString(), + 0, + 0/*dmpcb*/, google_breakpad::ExceptionHandler::HANDLER_ALL, MiniDumpNormal, - filename.toStdWString(), + _imp->crashReporterBreakpadPipe.toStdWString().c_str(), 0)); #endif @@ -3000,6 +3014,7 @@ bool interpretPythonScript(const std::string& script,std::string* error,std::str } if (error && !error->empty()) { + *error = "While executing script:\n" + script + "Python error:\n" + *error; return false; } return true; @@ -3307,4 +3322,40 @@ void getFunctionArguments(const std::string& pyFunc,std::string* error,std::vect } } +/** + * @brief Given a fullyQualifiedName, e.g: app1.Group1.Blur1 + * this function returns the PyObject attribute of Blur1 if it is defined, or Group1 otherwise + * If app1 or Group1 does not exist at this point, this is a failure. + **/ +PyObject* +getAttrRecursive(const std::string& fullyQualifiedName,PyObject* parentObj,bool* isDefined) +{ + std::size_t foundDot = fullyQualifiedName.find("."); + std::string attrName = foundDot == std::string::npos ? fullyQualifiedName : fullyQualifiedName.substr(0, foundDot); + PyObject* obj = 0; + if (PyObject_HasAttrString(parentObj, attrName.c_str())) { + obj = PyObject_GetAttrString(parentObj, attrName.c_str()); + } + + ///We either found the parent object or we are on the last object in which case we return the parent + if (!obj) { + //assert(fullyQualifiedName.find(".") == std::string::npos); + *isDefined = false; + return parentObj; + } else { + std::string recurseName; + if (foundDot != std::string::npos) { + recurseName = fullyQualifiedName; + recurseName.erase(0, foundDot + 1); + } + if (!recurseName.empty()) { + return getAttrRecursive(recurseName, obj, isDefined); + } else { + *isDefined = true; + return obj; + } + } + +} + } //Namespace Natron diff --git a/Engine/AppManager.h b/Engine/AppManager.h index a5a1702ca9..77dd6bca10 100644 --- a/Engine/AppManager.h +++ b/Engine/AppManager.h @@ -48,9 +48,6 @@ CLANG_DIAG_ON(deprecated) /*macro to get the unique pointer to the controler*/ #define appPTR AppManager::instance() -class QMutex; -class QChar; - namespace Natron { enum AppInstanceStatusEnum @@ -60,14 +57,6 @@ enum AppInstanceStatusEnum }; } -namespace OFX { - namespace Host { - namespace ImageEffect { - class ImageEffectPlugin; - class Descriptor; - } - } -} struct AppInstanceRef { @@ -674,6 +663,13 @@ bool getGroupInfos(const std::string& modulePath, // Does not work for functions with var args void getFunctionArguments(const std::string& pyFunc,std::string* error,std::vector* args); +/** +* @brief Given a fullyQualifiedName, e.g: app1.Group1.Blur1 +* this function returns the PyObject attribute of Blur1 if it is defined, or Group1 otherwise +* If app1 or Group1 does not exist at this point, this is a failure. +**/ +PyObject* getAttrRecursive(const std::string& fullyQualifiedName,PyObject* parentObj,bool* isDefined); + /** * @brief Small helper class to use as RAII to hold the GIL (Global Interpreter Lock) before calling ANY Python code. **/ diff --git a/Engine/AppManagerPrivate.cpp b/Engine/AppManagerPrivate.cpp index 93a8ce512b..cf8048a0ee 100644 --- a/Engine/AppManagerPrivate.cpp +++ b/Engine/AppManagerPrivate.cpp @@ -128,26 +128,37 @@ AppManagerPrivate::initBreakpad() assert(!breakpadHandler); std::srand(2000); - QString filename; - int handle; + + /* + Use a temporary file to get a random file name for the pipes. + We use 2 different pipe: 1 for the CrashReporter to notify to Natron that it has started correctly, and another + one that is used by the google_breakpad server itself. + */ + QString tmpFileName; { QTemporaryFile tmpf(NATRON_APPLICATION_NAME "_CRASH_PIPE_"); tmpf.open(); - handle = tmpf.handle(); - filename = tmpf.fileName(); + tmpFileName = tmpf.fileName(); tmpf.remove(); } + int handle = 0; - QString comPipeFilename = filename + "_COM_PIPE_"; + QString natronCrashReporterPipeFilename = tmpFileName + "_COM_PIPE_"; crashClientServer.reset(new QLocalServer()); QObject::connect(crashClientServer.get(),SIGNAL( newConnection() ),appPTR,SLOT( onNewCrashReporterConnectionPending() ) ); - crashClientServer->listen(comPipeFilename); + crashClientServer->listen(natronCrashReporterPipeFilename); - crashReporterBreakpadPipe = filename; +#ifdef Q_OS_LINUX + crashReporterBreakpadPipe.setFileName(tmpFileName); + crashReporterBreakpadPipe.open(QIODevice::ReadWrite); + handle = crashReporterBreakpadPipe.handle(); +#else + crashReporterBreakpadPipe = tmpFileName; +#endif QStringList args; - args << filename; + args << tmpFileName; args << QString::number(handle); - args << comPipeFilename; + args << natronCrashReporterPipeFilename; crashReporter.reset(new QProcess); QString crashReporterBinaryPath = qApp->applicationDirPath() + "/NatronCrashReporter"; crashReporter->start(crashReporterBinaryPath, args); diff --git a/Engine/AppManagerPrivate.h b/Engine/AppManagerPrivate.h index 06d6ecad5a..deea05fd95 100644 --- a/Engine/AppManagerPrivate.h +++ b/Engine/AppManagerPrivate.h @@ -114,7 +114,11 @@ struct AppManagerPrivate #ifdef NATRON_USE_BREAKPAD boost::shared_ptr breakpadHandler; boost::shared_ptr crashReporter; +#ifdef Q_OS_LINUX + QFile crashReporterBreakpadPipe; +#else QString crashReporterBreakpadPipe; +#endif boost::shared_ptr crashClientServer; QLocalSocket* crashServerConnection; #endif diff --git a/Engine/Bezier.cpp b/Engine/Bezier.cpp index 9e9aec87ac..4f3059c19b 100644 --- a/Engine/Bezier.cpp +++ b/Engine/Bezier.cpp @@ -1042,6 +1042,7 @@ Bezier::addControlPointAfterIndex(int index, setKeyframe(currentTime); } if (!useGuiCurve) { + QMutexLocker l(&itemMutex); copyInternalPointsToGuiPoints(); } } diff --git a/Engine/Bezier.h b/Engine/Bezier.h index dc1e1f5a5d..32f4f85014 100644 --- a/Engine/Bezier.h +++ b/Engine/Bezier.h @@ -44,33 +44,12 @@ CLANG_DIAG_ON(deprecated-declarations) #include "Engine/RotoDrawableItem.h" #include "Engine/EngineFwd.h" -#define kRotoLayerBaseName "Layer" -#define kRotoBezierBaseName "Bezier" -#define kRotoOpenBezierBaseName "Pencil" -#define kRotoEllipseBaseName "Ellipse" -#define kRotoRectangleBaseName "Rectangle" -#define kRotoPaintBrushBaseName "Brush" -#define kRotoPaintEraserBaseName "Eraser" -#define kRotoPaintBlurBaseName "Blur" -#define kRotoPaintSmearBaseName "Smear" -#define kRotoPaintSharpenBaseName "Sharpen" -#define kRotoPaintCloneBaseName "Clone" -#define kRotoPaintRevealBaseName "Reveal" -#define kRotoPaintDodgeBaseName "Dodge" -#define kRotoPaintBurnBaseName "Burn" - - -typedef struct _cairo_pattern cairo_pattern_t; /** * @class A base class for all items made by the roto context **/ -namespace Transform { -struct Matrix3x3; -} - /** * @class This class represents a bezier curve. diff --git a/Engine/Cache.h b/Engine/Cache.h index a16927a5e6..3538b01fe5 100644 --- a/Engine/Cache.h +++ b/Engine/Cache.h @@ -42,7 +42,6 @@ GCC_DIAG_OFF(deprecated) #include #include #include -#include #include #include GCC_DIAG_ON(deprecated) @@ -1149,22 +1148,26 @@ class Cache std::size_t getMaximumSize() const { - QMutexLocker k(&_sizeLock); return _maximumCacheSize; + QMutexLocker k(&_sizeLock); + return _maximumCacheSize; } std::size_t getMaximumMemorySize() const { - QMutexLocker k(&_sizeLock); return _maximumInMemorySize; + QMutexLocker k(&_sizeLock); + return _maximumInMemorySize; } std::size_t getMemoryCacheSize() const { - QMutexLocker k(&_sizeLock); return _memoryCacheSize; + QMutexLocker k(&_sizeLock); + return _memoryCacheSize; } std::size_t getDiskCacheSize() const { - QMutexLocker k(&_sizeLock); return _diskCacheSize; + QMutexLocker k(&_sizeLock); + return _diskCacheSize; } CacheSignalEmitter* activateSignalEmitter() const diff --git a/Engine/DockablePanelI.h b/Engine/DockablePanelI.h index a9a2844b7e..c16fe350e5 100644 --- a/Engine/DockablePanelI.h +++ b/Engine/DockablePanelI.h @@ -39,6 +39,8 @@ class DockablePanelI /** * @brief Must scan for new knobs and rebuild the panel accordingly **/ - virtual void scanForNewKnobs() = 0; + virtual void scanForNewKnobs(bool restorePageIndex = true) = 0; + virtual void deleteKnobGui(const boost::shared_ptr& knob) = 0; + }; #endif // DOCKABLEPANELI_H diff --git a/Engine/EffectInstance.cpp b/Engine/EffectInstance.cpp index 5b35cb3414..46dc4df0b3 100644 --- a/Engine/EffectInstance.cpp +++ b/Engine/EffectInstance.cpp @@ -251,8 +251,8 @@ EffectInstance::invalidateParallelRenderArgsTLS() --args.validArgs; if (args.validArgs < 0) { args.validArgs = 0; + return; } - for (NodeList::iterator it = args.rotoPaintNodes.begin(); it != args.rotoPaintNodes.end(); ++it) { (*it)->getLiveInstance()->invalidateParallelRenderArgsTLS(); } @@ -350,7 +350,7 @@ EffectInstance::aborted() const ///Rendering issued by RenderEngine::renderCurrentFrame, if time or hash changed, abort bool ret = !getNode()->isActivated(); - + return ret; } else { bool deactivated = !getNode()->isActivated(); @@ -760,7 +760,7 @@ EffectInstance::getImage(int inputNb, inputImg = roto->renderMaskFromStroke(attachedStroke, pixelRoI, requestComps, time, view, depth, mipMapLevel); if ( roto->isDoingNeatRender() ) { - getNode()->updateStrokeImage(inputImg); + getApp()->updateStrokeImage(inputImg, 0, false); } } } @@ -2514,10 +2514,21 @@ EffectInstance::evaluate(KnobI* knob, ///increments the knobs age following a change if (!button && isSignificant) { + abortAnyEvaluation(); node->incrementKnobsAge(); node->refreshIdentityState(); } + + /* + We always have to trigger a render because this might be a tree not connected via a link to the knob who changed + but just an expression + + if (reason == Natron::eValueChangedReasonSlaveRefresh) { + //do not trigger a render, the master will do it already + return; + }*/ + double time = getCurrentTime(); std::list viewers; @@ -3457,12 +3468,14 @@ EffectInstance::getComponentsAvailableRecursive(bool useLayerChoice, } if (doHeuristicForPassThrough) { - getNonMaskInputsAvailableComponents(time, view, false, comps, markedNodes); - } else { - if (ptInput) { - ptInput->getLiveInstance()->getComponentsAvailableRecursive(useLayerChoice, time, view, comps, markedNodes); - } + ptInput = node->getInput(node->getPreferredInput()); + //getNonMaskInputsAvailableComponents(time, view, false, comps, markedNodes); } + //else { + if (ptInput) { + ptInput->getLiveInstance()->getComponentsAvailableRecursive(useLayerChoice, time, view, comps, markedNodes); + } + //} } if (processAll) { //The node makes available everything available upstream @@ -3879,22 +3892,21 @@ EffectInstance::onKnobValueChanged_public(KnobI* k, ////tries to call getImage it can render with good parameters. - ParallelRenderArgsSetter frameRenderArgs( getApp()->getProject().get(), - time, - 0, /*view*/ - true, - false, - false, - 0, - node, - 0, // request - 0, //texture index - getApp()->getTimeLine().get(), - NodePtr(), - true, - false, - false, - boost::shared_ptr() ); + ParallelRenderArgsSetter frameRenderArgs(time, + 0, /*view*/ + true, + false, + false, + 0, + node, + 0, // request + 0, //texture index + getApp()->getTimeLine().get(), + NodePtr(), + true, + false, + false, + boost::shared_ptr() ); RECURSIVE_ACTION(); EffectPointerThreadProperty_RAII propHolder_raii(this); @@ -4194,7 +4206,7 @@ EffectInstance::abortAnyEvaluation() assert(node); - node->incrementKnobsAge(); + // node->incrementKnobsAge(); std::list outputNodes; NodeGroup* isGroup = dynamic_cast(this); diff --git a/Engine/EffectInstancePrivate.cpp b/Engine/EffectInstancePrivate.cpp index 7780f6420f..43dd82bdf9 100644 --- a/Engine/EffectInstancePrivate.cpp +++ b/Engine/EffectInstancePrivate.cpp @@ -404,7 +404,9 @@ EffectInstance::Implementation::runChangedParamCallback(KnobI* k, std::string thisGroupVar; NodeGroup* isParentGrp = dynamic_cast( collection.get() ); if (isParentGrp) { - thisGroupVar = appID + "." + isParentGrp->getNode()->getFullyQualifiedName(); + std::string nodeName = isParentGrp->getNode()->getFullyQualifiedName(); + std::string nodeFullName = appID + "." + nodeName; + thisGroupVar = nodeFullName; } else { thisGroupVar = appID; } diff --git a/Engine/EffectInstanceRenderRoI.cpp b/Engine/EffectInstanceRenderRoI.cpp index 1bf91bcf26..43bb09cb27 100644 --- a/Engine/EffectInstanceRenderRoI.cpp +++ b/Engine/EffectInstanceRenderRoI.cpp @@ -245,7 +245,7 @@ EffectInstance::renderRoI(const RenderRoIArgs & args, ParallelRenderArgs & frameRenderArgs = _imp->frameRenderArgs.localData(); if (!frameRenderArgs.validArgs) { - qDebug() << "Thread-storage for the render of the frame was not set, this is a bug."; + qDebug() << "[BUG]:" << getScriptName_mt_safe().c_str() << "Thread-storage for the render of the frame was not set."; frameRenderArgs.time = args.time; frameRenderArgs.nodeHash = getHash(); frameRenderArgs.view = args.view; @@ -894,12 +894,14 @@ EffectInstance::renderRoI(const RenderRoIArgs & args, std::list rectsLeftToRender; bool isDuringPaintStroke = isDuringPaintStrokeCreationThreadLocal(); bool fillGrownBoundsWithZeroes = false; + + //While painting, clear only the needed portion of the bitmap RectI lastStrokePixelRoD; if ( isDuringPaintStroke && args.inputImagesList.empty() ) { RectD lastStrokeRoD; NodePtr node = getNode(); if ( !node->isLastPaintStrokeBitmapCleared() ) { - node->getLastPaintStrokeRoD(&lastStrokeRoD); + lastStrokeRoD = getApp()->getLastPaintStrokeBbox(); node->clearLastPaintStrokeRoD(); // qDebug() << getScriptName_mt_safe().c_str() << "last stroke RoD: " << lastStrokeRoD.x1 << lastStrokeRoD.y1 << lastStrokeRoD.x2 << lastStrokeRoD.y2; lastStrokeRoD.toPixelEnclosing(mipMapLevel, par, &lastStrokePixelRoD); diff --git a/Engine/EngineFwd.h b/Engine/EngineFwd.h index 13c31c5b5d..0db0550693 100644 --- a/Engine/EngineFwd.h +++ b/Engine/EngineFwd.h @@ -25,16 +25,61 @@ #include // ***** END PYTHON BLOCK ***** -namespace boost { namespace serialization { class access; } } +// boost namespace boost { namespace archive { class xml_iarchive; class xml_oarchive; } +namespace serialization { +class access; +} } - class AbstractOfxEffectInstance; + + +// Qt + +class QChar; +class QDateTime; +class QFileInfo; +class QLocalServer; +class QLocalSocket; +class QMutex; +class QSettings; +class QString; +class QStringList; +class QTimer; +class QWaitCondition; + +// cairo + +typedef struct _cairo_pattern cairo_pattern_t; + + +// OpenFX + +namespace OFX { +namespace Host { +class Plugin; +namespace Property { +class Set; +} +namespace ImageEffect { +class ImageEffectPlugin; +class Descriptor; +} +} +} + +// SequenceParsing +namespace SequenceParsing { +class SequenceFromFiles; +} + +// Natron Engine + class AppInstance; class AppSettings; class Bezier; @@ -78,6 +123,7 @@ class KnobOutputFile; class KnobPage; class KnobParametric; class KnobPath; +class KnobSeparator; class KnobSerialization; class KnobString; class NodeCollection; @@ -88,32 +134,40 @@ class NodeSettingsPanel; class OfxClipInstance; class OfxEffectInstance; class OfxImage; +class OpenGLViewerI; class OutputFileParam; class OverlaySupport; class PageParam; +class ParallelRenderArgsSetter; class Param; class ParametricParam; class PathParam; +class PluginGroupNode; class PluginMemory; class ProcessHandler; class ProcessInputChannel; -class QMutex; +class ProjectSerialization; class RectD; class RectI; class RenderEngine; class RenderStats; +class RenderingFlagSetter; +class RequestedFrame; class RichText_Knob; class Roto; class RotoContext; class RotoDrawableItem; +class RotoItem; class RotoItemSerialization; class RotoLayer; +class RotoPoint; +class RotoStrokeItem; class Settings; class StringAnimationManager; class StringParam; +class TextureRect; class TimeLine; class ViewerInstance; -struct TextureRect; namespace Natron { class CacheSignalEmitter; @@ -135,10 +189,16 @@ class OfxParamOverlayInteract; class OutputEffectInstance; class Plugin; class Project; +namespace Color { +class Lut; +} } namespace Transform { struct Matrix3x3; } + + + #endif // Engine_EngineFwd_h diff --git a/Engine/FitCurve.h b/Engine/FitCurve.h index 0a1c2609e4..28be73092b 100644 --- a/Engine/FitCurve.h +++ b/Engine/FitCurve.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef Natron_Engine_FitCurve_h #define Natron_Engine_FitCurve_h diff --git a/Engine/GroupInput.cpp b/Engine/GroupInput.cpp index baea090a0f..dfdf3c5903 100644 --- a/Engine/GroupInput.cpp +++ b/Engine/GroupInput.cpp @@ -79,3 +79,29 @@ GroupInput::knobChanged(KnobI* k, } } + +Natron::ImagePremultiplicationEnum +GroupInput::getOutputPremultiplication() const +{ + NodePtr thisNode = getNode(); + boost::shared_ptr group = thisNode->getGroup(); + NodeGroup* isGroup = dynamic_cast(group.get()); + assert(isGroup); + int inputNb = -1; + std::vector groupInputs; + isGroup->getInputs(&groupInputs); + for (std::size_t i = 0; i < groupInputs.size(); ++i) { + if (groupInputs[i] == thisNode) { + inputNb = i; + break; + } + } + assert(inputNb != -1); + if (inputNb != -1) { + Natron::EffectInstance* input = isGroup->getInput(inputNb); + if (input) { + return input->getOutputPremultiplication(); + } + } + return Natron::eImagePremultiplicationPremultiplied; +} diff --git a/Engine/GroupInput.h b/Engine/GroupInput.h index bc46dc9c96..9aeaaed83a 100644 --- a/Engine/GroupInput.h +++ b/Engine/GroupInput.h @@ -85,6 +85,8 @@ class GroupInput double /*time*/, bool /*originatedFromMainThread*/) OVERRIDE FINAL; + virtual Natron::ImagePremultiplicationEnum getOutputPremultiplication() const OVERRIDE FINAL WARN_UNUSED_RETURN; + }; diff --git a/Engine/ImageComponents.h b/Engine/ImageComponents.h index 755f473844..8d1f71fe88 100644 --- a/Engine/ImageComponents.h +++ b/Engine/ImageComponents.h @@ -19,6 +19,12 @@ #ifndef IMAGECOMPONENTS_H #define IMAGECOMPONENTS_H +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + #include #include diff --git a/Engine/ImageCopyChannels.cpp b/Engine/ImageCopyChannels.cpp index 5109156f25..46e9ed76bb 100644 --- a/Engine/ImageCopyChannels.cpp +++ b/Engine/ImageCopyChannels.cpp @@ -26,6 +26,8 @@ #include +//#define NATRON_COPY_CHANNELS_UNPREMULT + using namespace Natron; template @@ -130,6 +132,7 @@ Image::copyUnProcessedChannelsForPremult(const RectI& roi, # endif } if (doA) { +#ifdef NATRON_COPY_CHANNELS_UNPREMULT if (premult) { if (dstAorig != 0) { // unpremult, then premult @@ -153,6 +156,7 @@ Image::copyUnProcessedChannelsForPremult(const RectI& roi, } } } +# endif if (dstNComps == 1 || dstNComps == 4) { dst_pixels[dstNComps - 1] = srcA; # ifdef DEBUG @@ -241,6 +245,7 @@ Image::copyUnProcessedChannelsForPremult(bool doR, bool doG, bool doB, bool doA, # endif } if (doA) { +#ifdef NATRON_COPY_CHANNELS_UNPREMULT if (premult) { if (dstAorig != 0) { // unpremult, then premult @@ -264,6 +269,7 @@ Image::copyUnProcessedChannelsForPremult(bool doR, bool doG, bool doB, bool doA, } } } +# endif if (dstNComps == 1 || dstNComps == 4) { dst_pixels[dstNComps - 1] = srcA; # ifdef DEBUG diff --git a/Engine/ImageParamsSerialization.h b/Engine/ImageParamsSerialization.h index 7bee62e560..9dba732ae5 100644 --- a/Engine/ImageParamsSerialization.h +++ b/Engine/ImageParamsSerialization.h @@ -46,7 +46,6 @@ GCC_DIAG_ON(unused-parameter) #include "Engine/EngineFwd.h" -using namespace Natron; namespace boost { namespace serialization { @@ -64,6 +63,8 @@ serialize(Archive & ar, } } +namespace Natron { + template void ImageComponents::serialize(Archive & ar, @@ -88,4 +89,6 @@ ImageParams::serialize(Archive & ar, ar & boost::serialization::make_nvp("MMLevel",_mipMapLevel); } +} // namespace Natron + #endif // IMAGEPARAMSSERIALIZATION_H diff --git a/Engine/Knob.cpp b/Engine/Knob.cpp index 839de12c00..6264d9cda6 100644 --- a/Engine/Knob.cpp +++ b/Engine/Knob.cpp @@ -71,24 +71,6 @@ KnobSignalSlotHandler::onAnimationRemoved(int dimension) getKnob()->onAnimationRemoved(dimension); } -void -KnobSignalSlotHandler::onMasterChanged(int dimension, int /*reason*/) -{ - KnobSignalSlotHandler* handler = qobject_cast( sender() ); - - assert(handler); - getKnob()->onMasterChanged(handler->getKnob().get(), dimension); -} - -void -KnobSignalSlotHandler::onExprDependencyChanged(int dimension, int /*reason*/) -{ - KnobSignalSlotHandler* handler = qobject_cast( sender() ); - - assert(handler); - getKnob()->onExprDependencyChanged(handler->getKnob().get(), dimension); - -} void KnobSignalSlotHandler::onMasterKeyFrameSet(double time,int dimension,int reason,bool added) @@ -445,9 +427,15 @@ KnobHelper::deleteKnob() if (!knob) { continue; } + boost::shared_ptr aliasKnob = knob->getAliasMaster(); + if (aliasKnob.get() == this) { + knob->setKnobAsAliasOfThis(aliasKnob, false); + } for (int i = 0; i < knob->getDimension(); ++i) { knob->clearExpression(i,true); + knob->unSlave(i, false); } + } for (int i = 0; i < getDimension(); ++i) { @@ -479,10 +467,7 @@ KnobHelper::deleteKnob() _imp->holder->removeDynamicKnob(it->get()); } } - if (_imp->gui) { - _imp->gui->onKnobDeletion(); - } - + KnobHolder* holder = getHolder(); if (holder) { Natron::EffectInstance* effect = dynamic_cast(holder); @@ -667,9 +652,9 @@ KnobHelper::deleteValueAtTime(Natron::CurveChangeReason curveChangeReason, bool useGuiCurve = (!holder || !holder->isSetValueCurrentlyPossible()) && _imp->gui; if (!useGuiCurve) { - if (holder) { + /*if (holder) { holder->abortAnyEvaluation(); - } + }*/ curve = _imp->curves[dimension]; } else { curve = _imp->gui->getCurve(dimension); @@ -697,9 +682,7 @@ KnobHelper::deleteValueAtTime(Natron::CurveChangeReason curveChangeReason, if (!useGuiCurve) { - if (_signalSlotHandler) { - _signalSlotHandler->s_updateDependencies(dimension, (int)reason); - } + checkAnimationLevel(dimension); guiCurveCloneInternalCurve(curveChangeReason,dimension, reason); evaluateValueChange(dimension,time,reason); @@ -738,9 +721,9 @@ KnobHelper::moveValueAtTime(Natron::CurveChangeReason reason, double time,int di bool useGuiCurve = (!holder || !holder->isSetValueCurrentlyPossible()) && _imp->gui; if (!useGuiCurve) { - if (holder) { + /*if (holder) { holder->abortAnyEvaluation(); - } + }*/ curve = _imp->curves[dimension]; } else { curve = _imp->gui->getCurve(dimension); @@ -824,9 +807,9 @@ KnobHelper::transformValueAtTime(Natron::CurveChangeReason curveChangeReason, do bool useGuiCurve = (!holder || !holder->isSetValueCurrentlyPossible()) && _imp->gui; if (!useGuiCurve) { - if (holder) { + /*if (holder) { holder->abortAnyEvaluation(); - } + }*/ curve = _imp->curves[dimension]; } else { curve = _imp->gui->getCurve(dimension); @@ -898,9 +881,9 @@ KnobHelper::cloneCurve(int dimension,const Curve& curve) boost::shared_ptr thisCurve; bool useGuiCurve = (!holder || !holder->isSetValueCurrentlyPossible()) && _imp->gui; if (!useGuiCurve) { - if (holder) { + /*if (holder) { holder->abortAnyEvaluation(); - } + }*/ thisCurve = _imp->curves[dimension]; } else { thisCurve = _imp->gui->getCurve(dimension); @@ -947,9 +930,9 @@ KnobHelper::setInterpolationAtTime(Natron::CurveChangeReason reason,int dimensio bool useGuiCurve = (!holder || !holder->isSetValueCurrentlyPossible()) && _imp->gui; if (!useGuiCurve) { - if (holder) { + /* if (holder) { holder->abortAnyEvaluation(); - } + }*/ curve = _imp->curves[dimension]; } else { curve = _imp->gui->getCurve(dimension); @@ -996,9 +979,9 @@ KnobHelper::moveDerivativesAtTime(Natron::CurveChangeReason reason,int dimension bool useGuiCurve = (!holder || !holder->isSetValueCurrentlyPossible()) && _imp->gui; if (!useGuiCurve) { - if (holder) { + /* if (holder) { holder->abortAnyEvaluation(); - } + }*/ curve = _imp->curves[dimension]; } else { curve = _imp->gui->getCurve(dimension); @@ -1047,9 +1030,9 @@ KnobHelper::moveDerivativeAtTime(Natron::CurveChangeReason reason,int dimension, bool useGuiCurve = (!holder || !holder->isSetValueCurrentlyPossible()) && _imp->gui; if (!useGuiCurve) { - if (holder) { + /* if (holder) { holder->abortAnyEvaluation(); - } + }*/ curve = _imp->curves[dimension]; } else { curve = _imp->gui->getCurve(dimension); @@ -1105,9 +1088,9 @@ KnobHelper::removeAnimation(int dimension, bool useGuiCurve = (!holder || !holder->isSetValueCurrentlyPossible()) && _imp->gui; if (!useGuiCurve) { - if (holder) { + /*if (holder) { holder->abortAnyEvaluation(); - } + }*/ curve = _imp->curves[dimension]; } else { curve = _imp->gui->getCurve(dimension); @@ -1338,10 +1321,10 @@ KnobHelper::evaluateValueChange(int dimension, bool guiFrozen = app && _imp->gui && _imp->gui->isGuiFrozenForPlayback(); - /// For eValueChangedReasonTimeChanged we never call the instanceChangedAction and evaluate otherwise it would just throttle down + /// For eValueChangedReasonTimeChanged we never call the instanceChangedAction and evaluate otherwise it would just throttle /// the application responsiveness if (reason != Natron::eValueChangedReasonTimeChanged && _imp->holder) { - if ( ( app && !app->getProject()->isLoadingProject() /*&& !app->isCreatingPythonGroup()*/) || !app ) { + if (!app || !app->getProject()->isLoadingProject()) { if (_imp->holder->isEvaluationBlocked()) { _imp->holder->appendValueChange(this, time, reason); @@ -1356,11 +1339,20 @@ KnobHelper::evaluateValueChange(int dimension, if (!guiFrozen && _signalSlotHandler) { computeHasModifications(); - if (!app || time == app->getTimeLine()->currentFrame()) { + bool refreshWidget = !app || hasAnimation() || time == app->getTimeLine()->currentFrame(); + if (refreshWidget) { _signalSlotHandler->s_valueChanged(dimension,(int)reason); } - _signalSlotHandler->s_updateDependencies(dimension,(int)reason); - checkAnimationLevel(dimension); + if (reason != Natron::eValueChangedReasonSlaveRefresh) { + refreshListenersAfterValueChange(dimension); + } + if (dimension == -1) { + for (int i = 0; i < _imp->dimension; ++i) { + checkAnimationLevel(i); + } + } else { + checkAnimationLevel(dimension); + } } } @@ -1899,7 +1891,9 @@ KnobHelper::validateExpression(const std::string& expression,int dimension,bool NodePtr node = effect->getNode(); assert(node); std::string appID = getHolder()->getApp()->getAppIDString(); - std::string exprFuncPrefix = appID + "." + node->getFullyQualifiedName() + "." + getName() + "."; + std::string nodeName = node->getFullyQualifiedName(); + std::string nodeFullName = appID + "." + nodeName; + std::string exprFuncPrefix = nodeFullName + "." + getName() + "."; std::string exprFuncName; { std::stringstream tmpSs; @@ -2087,12 +2081,6 @@ KnobHelper::clearExpression(int dimension,bool clearResults) otherListeners.erase(firstFound); } - if (nbTimesFound == 1) { - ///Disconnect only if this knob is not a dependency in other dimension - QObject::disconnect(other->getSignalSlotHandler().get(), SIGNAL(updateDependencies(int,int)), _signalSlotHandler.get(), - SLOT(onExprDependencyChanged(int,int))); - } - { QWriteLocker otherMastersLocker(&other->_imp->mastersMutex); other->_imp->listeners = otherListeners; @@ -2215,7 +2203,7 @@ KnobHelper::isAnimationEnabled() const } void -KnobHelper::setName(const std::string & name) +KnobHelper::setName(const std::string & name,bool throwExceptions) { _imp->originalName = name; _imp->name = Natron::makeNameScriptFriendly(name); @@ -2242,6 +2230,34 @@ KnobHelper::setName(const std::string & name) } ++no; } while (foundItem); + + + Natron::EffectInstance* effect = dynamic_cast(_imp->holder); + if (effect) { + NodePtr node = effect->getNode(); + std::string effectScriptName = node->getScriptName_mt_safe(); + if (!effectScriptName.empty()) { + std::string newPotentialQualifiedName = node->getApp()->getAppIDString() + node->getFullyQualifiedName(); + newPotentialQualifiedName += '.'; + newPotentialQualifiedName += finalName; + + bool isAttrDefined = false; + (void)Natron::getAttrRecursive(newPotentialQualifiedName, appPTR->getMainModule(), &isAttrDefined); + if (isAttrDefined) { + std::stringstream ss; + ss << "A Python attribute with the same name (" << newPotentialQualifiedName << ") already exists."; + if (throwExceptions) { + throw std::runtime_error(ss.str()); + } else { + std::string err = ss.str(); + appPTR->writeToOfxLog_mt_safe(err.c_str()); + std::cerr << err << std::endl; + return; + } + } + + } + } _imp->name = finalName; } @@ -2530,7 +2546,6 @@ KnobHelper::slaveTo(int dimension, if (helper && helper->_signalSlotHandler && _signalSlotHandler) { - //QObject::connect( helper->_signalSlotHandler.get(), SIGNAL( updateSlaves(int,int) ), _signalSlotHandler.get(), SLOT( onMasterChanged(int,int) ) ); QObject::connect( helper->_signalSlotHandler.get(), SIGNAL( keyFrameSet(double,int,int,bool) ), _signalSlotHandler.get(), SLOT( onMasterKeyFrameSet(double,int,int,bool) ) ); QObject::connect( helper->_signalSlotHandler.get(), SIGNAL( keyFrameRemoved(double,int,int) ), @@ -2673,9 +2688,9 @@ KnobHelper::deleteAnimationConditional(double time,int dimension,Natron::ValueCh bool useGuiCurve = (!holder || !holder->isSetValueCurrentlyPossible()) && _imp->gui; if (!useGuiCurve) { - if (holder) { + /* if (holder) { holder->abortAnyEvaluation(); - } + }*/ curve = _imp->curves[dimension]; } else { curve = _imp->gui->getCurve(dimension); @@ -2691,9 +2706,6 @@ KnobHelper::deleteAnimationConditional(double time,int dimension,Natron::ValueCh if (!useGuiCurve) { - if (_signalSlotHandler) { - _signalSlotHandler->s_updateDependencies(dimension, (int)reason); - } checkAnimationLevel(dimension); guiCurveCloneInternalCurve(Natron::eCurveChangeReasonInternal,dimension, reason); evaluateValueChange(dimension, time ,reason); @@ -2815,64 +2827,96 @@ KnobHelper::getKeyFrameIndex(int dimension, return curve->keyFrameIndex(time); } + void -KnobHelper::onMasterChanged(KnobI* master, - int masterDimension) +KnobHelper::refreshListenersAfterValueChange(int dimension) { - ///Map to the good dimension - assert(QThread::currentThread() == qApp->thread()); - MastersMap masters; - { - QReadLocker l(&_imp->mastersMutex); - masters = _imp->masters; + std::list > listeners; + getListeners(listeners); + + if (listeners.empty()) { + return; } - for (U32 i = 0; i < masters.size(); ++i) { - if (masters[i].second.get() == master && masters[i].first == masterDimension) { - - if (getExpression(i).empty()) { - ///We still want to clone the master's dimension because otherwise we couldn't edit the curve e.g in the curve editor - ///For example we use it for roto knobs where selected beziers have their knobs slaved to the gui knobs - clone(master,i); - - evaluateValueChange(i, getCurrentTime(),Natron::eValueChangedReasonSlaveRefresh); + + double time = getCurrentTime(); + for (std::list >::iterator it = listeners.begin(); it!=listeners.end(); ++it) { + + KnobHelper* slaveKnob = dynamic_cast(it->get()); + assert(slaveKnob); + + ///Check for expression on listener + std::set dimensionsToEvaluate; + { + QMutexLocker k(&slaveKnob->_imp->expressionMutex); + for (int i = 0; i < slaveKnob->_imp->dimension; ++i) { + for (std::list >::iterator it2 = slaveKnob->_imp->expressions[i].dependencies.begin(); + it2 != slaveKnob->_imp->expressions[i].dependencies.end(); ++it2) { + if (it2->first == this && (it2->second == dimension || it2->second == -1 || dimension == -1)) { + dimensionsToEvaluate.insert(i); + } + } } - - return; } - } - -} - - -void -KnobHelper::onExprDependencyChanged(KnobI* knob,int dimensionChanged) -{ - std::set dimensionsToEvaluate; - { - QMutexLocker k(&_imp->expressionMutex); - for (int i = 0; i < _imp->dimension; ++i) { - for (std::list >::iterator it = _imp->expressions[i].dependencies.begin(); it != _imp->expressions[i].dependencies.end(); ++it) { - if (it->first == knob && (it->second == dimensionChanged || it->second == -1)) { - dimensionsToEvaluate.insert(i); + + ///Clear appropriate expression results + for (std::set::const_iterator it2 = dimensionsToEvaluate.begin(); it2 != dimensionsToEvaluate.end(); ++it2) { + { + QMutexLocker k(&_imp->mustCloneGuiCurvesMutex); + slaveKnob->_imp->mustClearExprResults[*it2] = true; + } + { + slaveKnob->clearExpressionsResults(*it2); + } + } + + ///Check for slave/master link + bool mustClone = false; + if (dimensionsToEvaluate.empty()) { + + QReadLocker k(&slaveKnob->_imp->mastersMutex); + int i = 0; + for (MastersMap::const_iterator it2 = slaveKnob->_imp->masters.begin(); it2 != slaveKnob->_imp->masters.end(); ++it2,++i) { + if (it2->second.get() == this) { + //We found a slave/master link + if (dimension == -1 || dimension == it2->first) { + ///We still want to clone the master's dimension because otherwise we couldn't edit the curve e.g in the curve editor + ///For example we use it for roto knobs where selected beziers have their knobs slaved to the gui knobs + + mustClone = true; + dimensionsToEvaluate.insert(i); + } } } + } - } - - KnobHolder* holder = getHolder(); - double time = getCurrentTime(); - for (std::set::const_iterator it = dimensionsToEvaluate.begin(); it != dimensionsToEvaluate.end(); ++it) { - if (holder && !holder->isSetValueCurrentlyPossible()) { - holder->abortAnyEvaluation(); - QMutexLocker k(&_imp->mustCloneGuiCurvesMutex); - _imp->mustClearExprResults[*it] = true; + + + if (dimensionsToEvaluate.empty()) { + continue; + } + + int dimChanged; + if (dimensionsToEvaluate.size() > 1) { + dimChanged = -1; } else { - clearExpressionsResults(*it); - evaluateValueChange(*it, time, Natron::eValueChangedReasonSlaveRefresh); + dimChanged = *dimensionsToEvaluate.begin(); } - } + + if (mustClone) { + ///We still want to clone the master's dimension because otherwise we couldn't edit the curve e.g in the curve editor + ///For example we use it for roto knobs where selected beziers have their knobs slaved to the gui knobs + slaveKnob->clone(this,dimChanged); + } + + slaveKnob->evaluateValueChange(dimChanged, time, Natron::eValueChangedReasonSlaveRefresh); + + //call recursively + slaveKnob->refreshListenersAfterValueChange(dimChanged); + + } // for all listeners } + void KnobHelper::cloneExpressions(KnobI* other,int dimension) { @@ -2940,14 +2984,8 @@ KnobHelper::addListener(bool isExpression,int fromExprDimension,int thisDimensio } } - if (!isExpression) { - if (!alreadyListening) { - QObject::connect(_signalSlotHandler.get() , SIGNAL( updateSlaves(int,int) ),slave->_signalSlotHandler.get() , SLOT( onMasterChanged(int,int) ) ); - } - } else { - if (!alreadyListening) { - QObject::connect(_signalSlotHandler.get() , SIGNAL( updateDependencies(int,int) ),slave->_signalSlotHandler.get() , SLOT( onExprDependencyChanged(int,int) ) ); - } + if (isExpression) { + QMutexLocker k(&slave->_imp->expressionMutex); slave->_imp->expressions[fromExprDimension].dependencies.push_back(std::make_pair(this,thisDimension)); } @@ -2967,9 +3005,6 @@ KnobHelper::removeListener(KnobI* knob) { KnobHelper* other = dynamic_cast(knob); assert(other); - if (other && other->_signalSlotHandler && _signalSlotHandler) { - QObject::disconnect( _signalSlotHandler.get(), SIGNAL( updateSlaves(int,int) ), other->_signalSlotHandler.get(), SLOT( onMasterChanged(int,int) ) ); - } QWriteLocker l(&_imp->mastersMutex); for (std::list >::iterator it = _imp->listeners.begin(); it != _imp->listeners.end(); ++it) { @@ -3127,7 +3162,15 @@ KnobHelper::setHasModifications(int dimension,bool value,bool lock) } boost::shared_ptr -KnobHelper::createDuplicateOnNode(Natron::EffectInstance* effect,bool makeAlias) +KnobHelper::createDuplicateOnNode(Natron::EffectInstance* effect, + const boost::shared_ptr& page, + const boost::shared_ptr& group, + int indexInParent, + bool makeAlias, + const std::string& newScriptName, + const std::string& newLabel, + const std::string& newToolTip, + bool refreshParams) { ///find-out to which node that master knob belongs to if (!getHolder()->getApp()) { @@ -3154,39 +3197,44 @@ KnobHelper::createDuplicateOnNode(Natron::EffectInstance* effect,bool makeAlias) KnobPage* isPage = dynamic_cast(this); KnobButton* isBtn = dynamic_cast(this); KnobParametric* isParametric = dynamic_cast(this); - - const std::string& nodeScriptName = isEffect->getNode()->getScriptName(); - std::string newKnobName = nodeScriptName + getName(); + //Ensure the group user page is created - boost::shared_ptr groupUserPageNode = effect->getOrCreateUserPageKnob(); + boost::shared_ptr destPage; + if (page) { + destPage = page; + } else { + destPage = effect->getOrCreateUserPageKnob(); + } boost::shared_ptr output; if (isBool) { - boost::shared_ptr newKnob = effect->createBoolKnob(newKnobName, getLabel()); + boost::shared_ptr newKnob = effect->createBoolKnob(newScriptName, newLabel); output = newKnob; } else if (isInt) { - boost::shared_ptr newKnob = effect->createIntKnob(newKnobName, getLabel(),getDimension()); + boost::shared_ptr newKnob = effect->createIntKnob(newScriptName, newLabel,getDimension()); newKnob->setMinimumsAndMaximums(isInt->getMinimums(), isInt->getMaximums()); newKnob->setDisplayMinimumsAndMaximums(isInt->getDisplayMinimums(),isInt->getDisplayMaximums()); output = newKnob; } else if (isDbl) { - boost::shared_ptr newKnob = effect->createDoubleKnob(newKnobName, getLabel(),getDimension()); + boost::shared_ptr newKnob = effect->createDoubleKnob(newScriptName, newLabel,getDimension()); newKnob->setMinimumsAndMaximums(isDbl->getMinimums(), isDbl->getMaximums()); newKnob->setDisplayMinimumsAndMaximums(isDbl->getDisplayMinimums(),isDbl->getDisplayMaximums()); output = newKnob; } else if (isChoice) { - boost::shared_ptr newKnob = effect->createChoiceKnob(newKnobName, getLabel()); - newKnob->populateChoices(isChoice->getEntries_mt_safe(),isChoice->getEntriesHelp_mt_safe()); + boost::shared_ptr newKnob = effect->createChoiceKnob(newScriptName, newLabel); + if (!makeAlias) { + newKnob->populateChoices(isChoice->getEntries_mt_safe(),isChoice->getEntriesHelp_mt_safe()); + } output = newKnob; } else if (isColor) { - boost::shared_ptr newKnob = effect->createColorKnob(newKnobName, getLabel(),getDimension()); + boost::shared_ptr newKnob = effect->createColorKnob(newScriptName, newLabel,getDimension()); newKnob->setMinimumsAndMaximums(isColor->getMinimums(), isColor->getMaximums()); newKnob->setDisplayMinimumsAndMaximums(isColor->getDisplayMinimums(),isColor->getDisplayMaximums()); output = newKnob; } else if (isString) { - boost::shared_ptr newKnob = effect->createStringKnob(newKnobName, getLabel()); + boost::shared_ptr newKnob = effect->createStringKnob(newScriptName, newLabel); if (isString->isLabel()) { newKnob->setAsLabel(); } @@ -3201,47 +3249,48 @@ KnobHelper::createDuplicateOnNode(Natron::EffectInstance* effect,bool makeAlias) } output = newKnob; } else if (isFile) { - boost::shared_ptr newKnob = effect->createFileKnob(newKnobName, getLabel()); + boost::shared_ptr newKnob = effect->createFileKnob(newScriptName, newLabel); if (isFile->isInputImageFile()) { newKnob->setAsInputImage(); } output = newKnob; } else if (isOutputFile) { - boost::shared_ptr newKnob = effect->createOuptutFileKnob(newKnobName, getLabel()); + boost::shared_ptr newKnob = effect->createOuptutFileKnob(newScriptName, newLabel); if (isOutputFile->isOutputImageFile()) { newKnob->setAsOutputImageFile(); } output = newKnob; } else if (isPath) { - boost::shared_ptr newKnob = effect->createPathKnob(newKnobName, getLabel()); + boost::shared_ptr newKnob = effect->createPathKnob(newScriptName, newLabel); if (isPath->isMultiPath()) { newKnob->setMultiPath(true); } output = newKnob; } else if (isGrp) { - boost::shared_ptr newKnob = effect->createGroupKnob(newKnobName, getLabel()); + boost::shared_ptr newKnob = effect->createGroupKnob(newScriptName, newLabel); if (isGrp->isTab()) { newKnob->setAsTab(); } output = newKnob; } else if (isPage) { - boost::shared_ptr newKnob = effect->createPageKnob(newKnobName, getLabel()); + boost::shared_ptr newKnob = effect->createPageKnob(newScriptName, newLabel); output = newKnob; } else if (isBtn) { - boost::shared_ptr newKnob = effect->createButtonKnob(newKnobName, getLabel()); + boost::shared_ptr newKnob = effect->createButtonKnob(newScriptName, newLabel); output = newKnob; } else if (isParametric) { - boost::shared_ptr newKnob = effect->createParametricKnob(newKnobName, getLabel(), isParametric->getDimension()); + boost::shared_ptr newKnob = effect->createParametricKnob(newScriptName, newLabel, isParametric->getDimension()); output = newKnob; } if (!output) { return boost::shared_ptr(); } + output->setName(newScriptName, true); output->setAsUserKnob(); output->cloneDefaultValues(this); output->clone(this); @@ -3249,9 +3298,22 @@ KnobHelper::createDuplicateOnNode(Natron::EffectInstance* effect,bool makeAlias) output->setAnimationEnabled(isAnimationEnabled()); } output->setEvaluateOnChange(getEvaluateOnChange()); - output->setHintToolTip(getHintToolTip()); - output->setAddNewLine(isNewLineActivated()); - groupUserPageNode->addKnob(output); + output->setHintToolTip(newToolTip); + output->setAddNewLine(true); + if (group) { + if (indexInParent == -1) { + group->addKnob(output); + } else { + group->insertKnob(indexInParent, output); + } + } else { + assert(destPage); + if (indexInParent == -1) { + destPage->addKnob(output); + } else { + destPage->insertKnob(indexInParent, output); + } + } effect->getNode()->declarePythonFields(); if (!makeAlias) { @@ -3262,9 +3324,9 @@ KnobHelper::createDuplicateOnNode(Natron::EffectInstance* effect,bool makeAlias) std::stringstream ss; if (isCollecGroup) { - ss << "thisGroup." << newKnobName; + ss << "thisGroup." << newScriptName; } else { - ss << "app." << effect->getNode()->getFullyQualifiedName() << "." << newKnobName; + ss << "app." << effect->getNode()->getFullyQualifiedName() << "." << newScriptName; } if (output->getDimension() > 1) { ss << ".get()[dimension]"; @@ -3284,7 +3346,9 @@ KnobHelper::createDuplicateOnNode(Natron::EffectInstance* effect,bool makeAlias) } else { setKnobAsAliasOfThis(output, true); } - effect->refreshKnobs(); + if (refreshParams) { + effect->refreshKnobs(); + } return output; } @@ -3297,6 +3361,17 @@ KnobHelper::setKnobAsAliasOfThis(const boost::shared_ptr& master, bool do return false; } + /* + For choices, copy exactly the menu entries because they have to be the same + */ + if (doAlias) { + KnobChoice* isChoice = dynamic_cast(master.get()); + if (isChoice) { + KnobChoice* thisChoice = dynamic_cast(this); + assert(thisChoice); + isChoice->populateChoices(thisChoice->getEntries_mt_safe(),thisChoice->getEntriesHelp_mt_safe()); + } + } beginChanges(); for (int i = 0; i < getDimension(); ++i) { @@ -3327,6 +3402,52 @@ KnobHelper::getAliasMaster() const return _imp->slaveForAlias; } +void +KnobHelper::getAllExpressionDependenciesRecursive(std::list >& nodes) const +{ + std::list deps; + { + QMutexLocker k(&_imp->expressionMutex); + for (int i = 0; i < _imp->dimension; ++i) { + for (std::list< std::pair >::const_iterator it = _imp->expressions[i].dependencies.begin(); + it != _imp->expressions[i].dependencies.end(); ++it) { + + if (std::find(deps.begin(), deps.end(), it->first) == deps.end()) { + deps.push_back(it->first); + } + + } + } + } + { + QReadLocker k(&_imp->mastersMutex); + for (int i = 0; i < _imp->dimension; ++i) { + if (_imp->masters[i].second) { + if (std::find(deps.begin(), deps.end(), _imp->masters[i].second.get()) == deps.end()) { + deps.push_back(_imp->masters[i].second.get()); + } + } + } + } + + std::list knobsToInspectRecursive; + for (std::list::iterator it = deps.begin(); it!=deps.end(); ++it) { + Natron::EffectInstance* effect = dynamic_cast((*it)->getHolder()); + if (effect) { + NodePtr node = effect->getNode(); + if (std::find(nodes.begin(), nodes.end(), node) == nodes.end()) { + nodes.push_back(node); + knobsToInspectRecursive.push_back(*it); + } + } + } + + + for (std::list::iterator it = knobsToInspectRecursive.begin(); it!=knobsToInspectRecursive.end(); ++it) { + (*it)->getAllExpressionDependenciesRecursive(nodes); + } +} + /***************************KNOB HOLDER******************************************/ struct KnobHolder::KnobHolderPrivate @@ -3472,6 +3593,19 @@ KnobHolder::insertKnob(int index, const boost::shared_ptr& k) } } +void +KnobHolder::removeKnobFromList(const KnobI* knob) +{ + QMutexLocker kk(&_imp->knobsMutex); + + for (std::vector >::iterator it = _imp->knobs.begin(); it!=_imp->knobs.end(); ++it) { + if (it->get() == knob) { + _imp->knobs.erase(it); + return; + } + } +} + void KnobHolder::setPanelPointer(DockablePanelI* gui) { @@ -3487,11 +3621,11 @@ KnobHolder::discardPanelPointer() } void -KnobHolder::refreshKnobs() +KnobHolder::refreshKnobs(bool keepCurPageIndex) { assert(QThread::currentThread() == qApp->thread()); if (_imp->settingsPanel) { - _imp->settingsPanel->scanForNewKnobs(); + _imp->settingsPanel->scanForNewKnobs(keepCurPageIndex); Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3509,9 +3643,12 @@ KnobHolder::removeDynamicKnob(KnobI* knob) QMutexLocker k(&_imp->knobsMutex); knobs = _imp->knobs; } + + boost::shared_ptr sharedKnob; for (std::vector >::iterator it = knobs.begin(); it != knobs.end(); ++it) { if (it->get() == knob && (*it)->isDynamicallyCreated()) { (*it)->deleteKnob(); + sharedKnob = *it; break; } } @@ -3521,64 +3658,115 @@ KnobHolder::removeDynamicKnob(KnobI* knob) for (std::vector >::iterator it2 = _imp->knobs.begin(); it2 != _imp->knobs.end(); ++it2) { if (it2->get() == knob && (*it2)->isDynamicallyCreated()) { _imp->knobs.erase(it2); - return; + break; } } } + if (_imp->settingsPanel) { + _imp->settingsPanel->deleteKnobGui(sharedKnob); + } + + } -void +bool KnobHolder::moveKnobOneStepUp(KnobI* knob) { - if (!knob->isUserKnob()) { - return; + if (!knob->isUserKnob() && !dynamic_cast(knob)) { + return false; } boost::shared_ptr parent = knob->getParentKnob(); KnobGroup* parentIsGrp = dynamic_cast(parent.get()); KnobPage* parentIsPage = dynamic_cast(parent.get()); //the knob belongs to a group/page , change its index within the group instead - if (parentIsGrp) { - parentIsGrp->moveOneStepUp(knob); - } else if (parentIsPage) { - parentIsPage->moveOneStepUp(knob); + bool moveOk = false; + if (!parent) { + moveOk = true; + } + try { + if (parentIsGrp) { + moveOk = parentIsGrp->moveOneStepUp(knob); + } else if (parentIsPage) { + moveOk = parentIsPage->moveOneStepUp(knob); + } + } catch (const std::exception& e) { + qDebug() << e.what(); + assert(false); + return false; } - QMutexLocker k(&_imp->knobsMutex); - int prevInPage = -1; - for (U32 i = 0; i < _imp->knobs.size(); ++i) { - if (_imp->knobs[i].get() == knob) { - if (prevInPage != -1) { - boost::shared_ptr tmp = _imp->knobs[prevInPage]; - _imp->knobs[prevInPage] = _imp->knobs[i]; - _imp->knobs[i] = tmp; + if (moveOk) { + QMutexLocker k(&_imp->knobsMutex); + int prevInPage = -1; + if (parent) { + for (U32 i = 0; i < _imp->knobs.size(); ++i) { + if (_imp->knobs[i].get() == knob) { + if (prevInPage != -1) { + boost::shared_ptr tmp = _imp->knobs[prevInPage]; + _imp->knobs[prevInPage] = _imp->knobs[i]; + _imp->knobs[i] = tmp; + } + break; + } else { + if (_imp->knobs[i]->isUserKnob() && (_imp->knobs[i]->getParentKnob() == parent)) { + prevInPage = i; + } + } } - break; } else { - if (_imp->knobs[i]->isUserKnob() && (_imp->knobs[i]->getParentKnob() == knob->getParentKnob())) { - prevInPage = i; + bool foundPrevPage = false; + for (U32 i = 0; i < _imp->knobs.size(); ++i) { + if (_imp->knobs[i].get() == knob) { + if (prevInPage != -1) { + boost::shared_ptr tmp = _imp->knobs[prevInPage]; + _imp->knobs[prevInPage] = _imp->knobs[i]; + _imp->knobs[i] = tmp; + foundPrevPage = true; + } + break; + } else { + if (!_imp->knobs[i]->getParentKnob()) { + prevInPage = i; + } + } + } + if (!foundPrevPage) { + moveOk = false; } } } - + return moveOk; } -void + + +bool KnobHolder::moveKnobOneStepDown(KnobI* knob) { - if (!knob->isUserKnob()) { - return; + if (!knob->isUserKnob() && !dynamic_cast(knob)) { + return false; } boost::shared_ptr parent = knob->getParentKnob(); KnobGroup* parentIsGrp = dynamic_cast(parent.get()); KnobPage* parentIsPage = dynamic_cast(parent.get()); //the knob belongs to a group/page , change its index within the group instead - if (parentIsGrp) { - parentIsGrp->moveOneStepDown(knob); - } else if (parentIsPage) { - parentIsPage->moveOneStepDown(knob); + bool moveOk = false; + if (!parent) { + moveOk = true; + } + try { + if (parentIsGrp) { + moveOk = parentIsGrp->moveOneStepDown(knob); + } else if (parentIsPage) { + moveOk = parentIsPage->moveOneStepDown(knob); + } + } catch (const std::exception& e) { + qDebug() << e.what(); + assert(false); + return false; } @@ -3592,21 +3780,41 @@ KnobHolder::moveKnobOneStepDown(KnobI* knob) } assert(foundIndex != -1); if (foundIndex < 0) { - return; + return false; } - for (int i = foundIndex + 1; i < (int)_imp->knobs.size(); ++i) { - if (_imp->knobs[i]->isUserKnob() && (_imp->knobs[i]->getParentKnob() == knob->getParentKnob())) { - boost::shared_ptr tmp = _imp->knobs[foundIndex]; - _imp->knobs[foundIndex] = _imp->knobs[i]; - _imp->knobs[i] = tmp; - break; + if (moveOk) { + //The knob (or page) could be moved inside the group/page, just move it down + if (parent) { + for (int i = foundIndex + 1; i < (int)_imp->knobs.size(); ++i) { + if (_imp->knobs[i]->isUserKnob() && (_imp->knobs[i]->getParentKnob() == parent)) { + boost::shared_ptr tmp = _imp->knobs[foundIndex]; + _imp->knobs[foundIndex] = _imp->knobs[i]; + _imp->knobs[i] = tmp; + break; + } + } + } else { + bool foundNextPage = false; + for (int i = foundIndex + 1; i < (int)_imp->knobs.size(); ++i) { + if (!_imp->knobs[i]->getParentKnob()) { + boost::shared_ptr tmp = _imp->knobs[foundIndex]; + _imp->knobs[foundIndex] = _imp->knobs[i]; + _imp->knobs[i] = tmp; + foundNextPage = true; + break; + } + } + + if (!foundNextPage) { + moveOk = false; + } } } - + return moveOk; } boost::shared_ptr -KnobHolder::getOrCreateUserPageKnob() +KnobHolder::getUserPageKnob() const { { QMutexLocker k(&_imp->knobsMutex); @@ -3616,9 +3824,22 @@ KnobHolder::getOrCreateUserPageKnob() } } } - boost::shared_ptr ret = Natron::createKnob(this,NATRON_USER_MANAGED_KNOBS_PAGE_LABEL,1,false); + return boost::shared_ptr(); +} + +boost::shared_ptr +KnobHolder::getOrCreateUserPageKnob() +{ + + boost::shared_ptr ret = getUserPageKnob(); + if (ret) { + return ret; + } + ret = Natron::createKnob(this,NATRON_USER_MANAGED_KNOBS_PAGE_LABEL,1,false); ret->setAsUserKnob(); ret->setName(NATRON_USER_MANAGED_KNOBS_PAGE); + + Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3636,8 +3857,8 @@ KnobHolder::createIntKnob(const std::string& name, const std::string& label,int boost::shared_ptr ret = Natron::createKnob(this,label, dimension, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3655,8 +3876,8 @@ KnobHolder::createDoubleKnob(const std::string& name, const std::string& label,i boost::shared_ptr ret = Natron::createKnob(this,label, dimension, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3674,8 +3895,8 @@ KnobHolder::createColorKnob(const std::string& name, const std::string& label,in boost::shared_ptr ret = Natron::createKnob(this,label, dimension, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3693,8 +3914,8 @@ KnobHolder::createBoolKnob(const std::string& name, const std::string& label) boost::shared_ptr ret = Natron::createKnob(this,label, 1, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3712,8 +3933,8 @@ KnobHolder::createChoiceKnob(const std::string& name, const std::string& label) boost::shared_ptr ret = Natron::createKnob(this,label, 1, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3731,8 +3952,8 @@ KnobHolder::createButtonKnob(const std::string& name, const std::string& label) boost::shared_ptr ret = Natron::createKnob(this,label, 1, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3751,8 +3972,8 @@ KnobHolder::createStringKnob(const std::string& name, const std::string& label) boost::shared_ptr ret = Natron::createKnob(this,label, 1, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3771,8 +3992,8 @@ KnobHolder::createFileKnob(const std::string& name, const std::string& label) boost::shared_ptr ret = Natron::createKnob(this,label, 1, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3790,8 +4011,8 @@ KnobHolder::createOuptutFileKnob(const std::string& name, const std::string& lab boost::shared_ptr ret = Natron::createKnob(this,label, 1, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3810,8 +4031,8 @@ KnobHolder::createPathKnob(const std::string& name, const std::string& label) boost::shared_ptr ret = Natron::createKnob(this,label, 1, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3830,8 +4051,8 @@ KnobHolder::createGroupKnob(const std::string& name, const std::string& label) boost::shared_ptr ret = Natron::createKnob(this,label, 1, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3850,8 +4071,8 @@ KnobHolder::createPageKnob(const std::string& name, const std::string& label) boost::shared_ptr ret = Natron::createKnob(this,label, 1, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -3870,8 +4091,8 @@ KnobHolder::createParametricKnob(const std::string& name, const std::string& lab boost::shared_ptr ret = Natron::createKnob(this,label, nbCurves, false); ret->setName(name); ret->setAsUserKnob(); - boost::shared_ptr pageknob = getOrCreateUserPageKnob(); - Q_UNUSED(pageknob); + /*boost::shared_ptr pageknob = getOrCreateUserPageKnob(); + Q_UNUSED(pageknob);*/ Natron::EffectInstance* isEffect = dynamic_cast(this); if (isEffect) { isEffect->getNode()->declarePythonFields(); @@ -4017,6 +4238,16 @@ KnobHolder::isSetValueCurrentlyPossible() const return canSetValue(); } + +void +KnobHolder::getAllExpressionDependenciesRecursive(std::list >& nodes) const +{ + QMutexLocker k(&_imp->knobsMutex); + for (std::vector >::const_iterator it = _imp->knobs.begin(); it!=_imp->knobs.end(); ++it) { + (*it)->getAllExpressionDependenciesRecursive(nodes); + } +} + KnobHolder::MultipleParamsEditEnum KnobHolder::getMultipleParamsEditLevel() const { diff --git a/Engine/Knob.h b/Engine/Knob.h index 8bfab3265a..278a9a563c 100644 --- a/Engine/Knob.h +++ b/Engine/Knob.h @@ -47,6 +47,12 @@ #define NATRON_USER_MANAGED_KNOBS_PAGE_LABEL "User" #define NATRON_USER_MANAGED_KNOBS_PAGE "userNatron" +class KnobPage; +class KnobGroup; +namespace Natron { + class Node; +} + class KnobSignalSlotHandler : public QObject { @@ -114,12 +120,7 @@ class KnobSignalSlotHandler Q_EMIT animationRemoved(dimension); } - void s_updateDependencies(int dimension,int reason) - { - Q_EMIT updateSlaves(dimension,reason); - Q_EMIT updateDependencies(dimension,reason); - } - + void s_knobSlaved(int dim, bool slaved) { @@ -213,13 +214,6 @@ public Q_SLOTS: * @brief Calls KnobI::onAnimationRemoved **/ void onAnimationRemoved(int dimension); - - /** - * @brief Calls KnobI::evaluateValueChange with a reason of Natron::eValueChangedReasonPluginEdited - **/ - void onMasterChanged(int,int); - - void onExprDependencyChanged(int,int); void onMasterKeyFrameSet(double time,int dimension,int reason,bool added); @@ -278,12 +272,6 @@ public Q_SLOTS: ///Emitted whenever all keyframes of a dimension are effectively removed void animationRemoved(int); - ///Emitted whenever setValueAtTime,setValue or deleteValueAtTime is called. It notifies slaves - ///of the changes that occured in this knob, letting them a chance to update their interface. - void updateSlaves(int dimension,int reason); - - void updateDependencies(int dimension,int reason); - ///Emitted whenever a knob is slaved via the slaveTo function with a reason of eValueChangedReasonPluginEdited. void knobSlaved(int,bool); @@ -594,10 +582,12 @@ class KnobI virtual std::string validateExpression(const std::string& expression,int dimension,bool hasRetVariable, std::string* resultAsString) = 0; - /** - * @brief Called whenever a dependency through expressions has changed its value. This function will refresh the GUI for this knob. - **/ - virtual void onExprDependencyChanged(KnobI* knob,int dimension) = 0; + +protected: + + virtual void refreshListenersAfterValueChange(int dimension) = 0; + +public: /** * @brief Returns whether the expr at the given dimension uses the ret variable to assign to the return value or not @@ -610,11 +600,6 @@ class KnobI **/ virtual bool getExpressionDependencies(int dimension, std::list >& dependencies) const = 0; - /** - * @brief Called when the master knob has changed its values or keyframes. - * @param masterDimension The dimension of the master which has changed - **/ - virtual void onMasterChanged(KnobI* master,int masterDimension) = 0; /** * @brief Calls setValueAtTime with a reason of Natron::eValueChangedReasonUserEdited. @@ -806,7 +791,7 @@ class KnobI * the GUI but what Natron uses internally to identify knobs from each other. By default the * name is the same as the getLabel(i.e: the text label). */ - virtual void setName(const std::string & name) = 0; + virtual void setName(const std::string & name, bool throwExceptions = false) = 0; /** * @brief Returns the knob name. By default the @@ -945,6 +930,8 @@ class KnobI **/ virtual void addListener(bool isExpression,int fromExprDimension, int thisDimension, const boost::shared_ptr& knob) = 0; + virtual void getAllExpressionDependenciesRecursive(std::list >& nodes) const = 0; + private: virtual void removeListener(KnobI* knob) = 0; public: @@ -979,7 +966,15 @@ class KnobI bool slaveTo(int dimension,const boost::shared_ptr & other,int otherDimension,bool ignoreMasterPersistence = false); virtual bool isMastersPersistenceIgnored() const = 0; - virtual boost::shared_ptr createDuplicateOnNode(Natron::EffectInstance* effect,bool makeAlias) = 0; + virtual boost::shared_ptr createDuplicateOnNode(Natron::EffectInstance* effect, + const boost::shared_ptr& page, + const boost::shared_ptr& group, + int indexInParent, + bool makeAlias, + const std::string& newScriptName, + const std::string& newLabel, + const std::string& newToolTip, + bool refreshParams) = 0; /** * @brief If a knob was created using createDuplicateOnNode(effect,true), this function will return true @@ -1153,7 +1148,6 @@ class KnobHelper virtual bool setInterpolationAtTime(Natron::CurveChangeReason reason,int dimension,double time,Natron::KeyframeTypeEnum interpolation,KeyFrame* newKey) OVERRIDE FINAL; virtual bool moveDerivativesAtTime(Natron::CurveChangeReason reason,int dimension,double time,double left,double right) OVERRIDE FINAL WARN_UNUSED_RETURN; virtual bool moveDerivativeAtTime(Natron::CurveChangeReason reason,int dimension,double time,double derivative,bool isLeft) OVERRIDE FINAL WARN_UNUSED_RETURN; - virtual void onMasterChanged(KnobI* master,int masterDimension) OVERRIDE FINAL; virtual void deleteAnimationBeforeTime(double time,int dimension,Natron::ValueChangedReasonEnum reason) OVERRIDE FINAL; virtual void deleteAnimationAfterTime(double time,int dimension,Natron::ValueChangedReasonEnum reason) OVERRIDE FINAL; @@ -1176,7 +1170,13 @@ class KnobHelper virtual void clearExpression(int dimension,bool clearResults) OVERRIDE FINAL; virtual std::string validateExpression(const std::string& expression,int dimension,bool hasRetVariable, std::string* resultAsString) OVERRIDE FINAL WARN_UNUSED_RETURN; - virtual void onExprDependencyChanged(KnobI* knob,int dimension) OVERRIDE FINAL; + +protected: + + virtual void refreshListenersAfterValueChange(int dimension) OVERRIDE FINAL; + +public: + virtual bool isExpressionUsingRetVariable(int dimension = 0) const OVERRIDE FINAL WARN_UNUSED_RETURN; virtual bool getExpressionDependencies(int dimension, std::list >& dependencies) const OVERRIDE FINAL; virtual std::string getExpression(int dimension) const OVERRIDE FINAL WARN_UNUSED_RETURN; @@ -1207,7 +1207,7 @@ class KnobHelper virtual bool getDefaultIsSecret() const OVERRIDE FINAL WARN_UNUSED_RETURN; virtual void setIsFrozen(bool frozen) OVERRIDE FINAL; virtual void setDirty(bool d) OVERRIDE FINAL; - virtual void setName(const std::string & name) OVERRIDE FINAL; + virtual void setName(const std::string & name,bool throwExceptions = false) OVERRIDE FINAL; virtual const std::string & getName() const OVERRIDE FINAL WARN_UNUSED_RETURN; virtual const std::string & getOriginalName() const OVERRIDE FINAL WARN_UNUSED_RETURN; virtual void setParentKnob(boost::shared_ptr knob) OVERRIDE FINAL; @@ -1243,7 +1243,15 @@ class KnobHelper virtual bool hasModifications(int dimension) const OVERRIDE FINAL WARN_UNUSED_RETURN; virtual bool hasModificationsForSerialization() const OVERRIDE FINAL WARN_UNUSED_RETURN; - virtual boost::shared_ptr createDuplicateOnNode(Natron::EffectInstance* effect,bool makeAlias) OVERRIDE FINAL WARN_UNUSED_RETURN; + virtual boost::shared_ptr createDuplicateOnNode(Natron::EffectInstance* effect, + const boost::shared_ptr& page, + const boost::shared_ptr& group, + int indexInParent, + bool makeAlias, + const std::string& newScriptName, + const std::string& newLabel, + const std::string& newToolTip, + bool refreshParams) OVERRIDE FINAL WARN_UNUSED_RETURN; virtual boost::shared_ptr getAliasMaster() const OVERRIDE FINAL WARN_UNUSED_RETURN; virtual bool setKnobAsAliasOfThis(const boost::shared_ptr& master, bool doAlias) OVERRIDE FINAL; @@ -1282,6 +1290,8 @@ class KnobHelper **/ virtual void addListener(bool isFromExpr,int fromExprDimension, int thisDimension, const boost::shared_ptr& knob) OVERRIDE FINAL; virtual void removeListener(KnobI* knob) OVERRIDE FINAL; + + virtual void getAllExpressionDependenciesRecursive(std::list >& nodes) const OVERRIDE FINAL; virtual void getListeners(std::list >& listeners) const OVERRIDE FINAL; @@ -1869,7 +1879,7 @@ class KnobHolder : public QObject void discardPanelPointer(); - void refreshKnobs(); + void refreshKnobs(bool keepCurPageIndex = true); /** * @brief Dynamically removes a knob (from the GUI also) @@ -1877,8 +1887,9 @@ class KnobHolder : public QObject void removeDynamicKnob(KnobI* knob); //To re-arrange user knobs only, does nothing if knob->isUserKnob() returns false - void moveKnobOneStepUp(KnobI* knob); - void moveKnobOneStepDown(KnobI* knob); + bool moveKnobOneStepUp(KnobI* knob); + bool moveKnobOneStepDown(KnobI* knob); + template boost::shared_ptr createKnob(const std::string &label, int dimension = 1) const WARN_UNUSED_RETURN; @@ -1949,6 +1960,8 @@ class KnobHolder : public QObject ////////////////////////////////////////////////////////////////////////////////////////// boost::shared_ptr getOrCreateUserPageKnob() ; + boost::shared_ptr getUserPageKnob() const; + /** * @brief These functions below are dynamic in a sense that they can be called at any time (on the main-thread) * to create knobs on the fly. Their gui will be properly created. In order to notify the GUI that new parameters were @@ -1993,6 +2006,8 @@ class KnobHolder : public QObject bool isSetValueCurrentlyPossible() const; + void getAllExpressionDependenciesRecursive(std::list >& nodes) const; + protected: ////////////////////////////////////////////////////////////////////////////////////////// @@ -2129,6 +2144,7 @@ class KnobHolder : public QObject void addKnob(boost::shared_ptr k); void insertKnob(int idx, const boost::shared_ptr& k); + void removeKnobFromList(const KnobI* knob); void initializeKnobsPublic(); diff --git a/Engine/KnobGuiI.h b/Engine/KnobGuiI.h index 599961fa62..ce2d6c294e 100644 --- a/Engine/KnobGuiI.h +++ b/Engine/KnobGuiI.h @@ -52,7 +52,6 @@ class KnobGuiI virtual void restoreOpenGLContext() = 0; virtual unsigned int getCurrentRenderScale() const { return 0; } virtual boost::shared_ptr getCurve(int dimension) const = 0; - virtual void onKnobDeletion() = 0; protected: ///Should set to the underlying knob the gui ptr diff --git a/Engine/KnobImpl.h b/Engine/KnobImpl.h index c686a9a53a..2a1b0b95d0 100644 --- a/Engine/KnobImpl.h +++ b/Engine/KnobImpl.h @@ -908,10 +908,10 @@ Knob::setValue(const T & v, - ///If we cannot set value, queue it + if (holder && !holder->isSetValueCurrentlyPossible()) { - - if (getEvaluateOnChange()) { + ///If we cannot set value, queue it + if (holder && getEvaluateOnChange()) { holder->abortAnyEvaluation(); } @@ -1231,12 +1231,14 @@ Knob::setValueAtTime(double time, assert(curve); makeKeyFrame(curve.get(), time, v, newKey); - ///If we cannot set value, queue it + if (holder && !holder->canSetValue()) { - if (getEvaluateOnChange()) { + ///If we cannot set value, queue it + if (holder && getEvaluateOnChange()) { holder->abortAnyEvaluation(); } + boost::shared_ptr qv(new QueuedSetValueAtTime(time,dimension,v,*newKey,reason)); { @@ -1393,8 +1395,6 @@ Knob::unSlave(int dimension, boost::shared_ptr helper = boost::dynamic_pointer_cast(master.second); if (helper->getSignalSlotHandler() && _signalSlotHandler) { - //QObject::disconnect( helper->getSignalSlotHandler().get(), SIGNAL( updateSlaves(int,int) ), _signalSlotHandler.get(), - // SLOT( onMasterChanged(int,int) ) ); QObject::disconnect( helper->getSignalSlotHandler().get(), SIGNAL( keyFrameSet(double,int,int,bool) ), _signalSlotHandler.get(), SLOT( onMasterKeyFrameSet(double,int,int,bool) ) ); QObject::disconnect( helper->getSignalSlotHandler().get(), SIGNAL( keyFrameRemoved(double,int,int) ), @@ -1688,9 +1688,9 @@ Knob::onKeyFrameSet(double time, if (!useGuiCurve) { assert(holder); - if (holder && getEvaluateOnChange()) { + /*if (holder && getEvaluateOnChange()) { holder->abortAnyEvaluation(); - } + }*/ curve = getCurve(dimension); } else { curve = getGuiCurve(dimension); @@ -1711,9 +1711,9 @@ Knob::setKeyFrame(const KeyFrame& key,int dimension,Natron::ValueChangedReaso if (!useGuiCurve) { assert(holder); - if (holder && getEvaluateOnChange()) { + /*if (holder && getEvaluateOnChange()) { holder->abortAnyEvaluation(); - } + }*/ curve = getCurve(dimension); } else { curve = getGuiCurve(dimension); @@ -2312,7 +2312,7 @@ Knob::clone(KnobI* other, } if (_signalSlotHandler) { _signalSlotHandler->s_valueChanged(dimension,Natron::eValueChangedReasonPluginEdited); - _signalSlotHandler->s_updateDependencies(dimension,Natron::eValueChangedReasonPluginEdited); + refreshListenersAfterValueChange(dimension); } cloneExtraData(other,dimension); if (getHolder()) { @@ -2354,7 +2354,7 @@ Knob::cloneAndCheckIfChanged(KnobI* other,int dimension) if (hasChanged) { if (_signalSlotHandler) { _signalSlotHandler->s_valueChanged(dimension,Natron::eValueChangedReasonPluginEdited); - _signalSlotHandler->s_updateDependencies(dimension,Natron::eValueChangedReasonPluginEdited); + refreshListenersAfterValueChange(dimension); } } hasChanged |= cloneExtraDataAndCheckIfChanged(other); @@ -2397,7 +2397,7 @@ Knob::clone(KnobI* other, } if (_signalSlotHandler) { _signalSlotHandler->s_valueChanged(dimension,Natron::eValueChangedReasonPluginEdited); - _signalSlotHandler->s_updateDependencies(dimension,Natron::eValueChangedReasonPluginEdited); + refreshListenersAfterValueChange(dimension); } cloneExtraData(other,offset,range,dimension); if (getHolder()) { @@ -2442,7 +2442,6 @@ Knob::cloneAndUpdateGui(KnobI* other,int dimension) } if (!keysList.empty()) { _signalSlotHandler->s_multipleKeyFramesSet(keysList, i, (int)Natron::eValueChangedReasonNatronInternalEdited); - _signalSlotHandler->s_updateDependencies(i, Natron::eValueChangedReasonPluginEdited); } } checkAnimationLevel(i); @@ -2451,6 +2450,7 @@ Knob::cloneAndUpdateGui(KnobI* other,int dimension) if (_signalSlotHandler) { _signalSlotHandler->s_valueChanged(dimension,Natron::eValueChangedReasonPluginEdited); } + refreshListenersAfterValueChange(dimension); cloneExtraData(other,dimension); if (getHolder()) { getHolder()->updateHasAnimation(); diff --git a/Engine/KnobSerialization.cpp b/Engine/KnobSerialization.cpp index a1c36a9547..ecc2ffbe67 100644 --- a/Engine/KnobSerialization.cpp +++ b/Engine/KnobSerialization.cpp @@ -158,7 +158,9 @@ KnobSerialization::restoreKnobLinks(const boost::shared_ptr & knob, int i = 0; if (_masterIsAlias) { - assert(!_masters.empty()); + /* + * _masters can be empty for example if we expand a group: the slaved knobs are no longer slaves + */ if (!_masters.empty()) { const std::string& aliasKnobName = _masters.front().masterKnobName; const std::string& aliasNodeName = _masters.front().masterNodeName; diff --git a/Engine/KnobTypes.cpp b/Engine/KnobTypes.cpp index c079cdbc69..e49567c2a2 100644 --- a/Engine/KnobTypes.cpp +++ b/Engine/KnobTypes.cpp @@ -848,12 +848,8 @@ KnobChoice::choiceRestoration(KnobChoice* knob,const ChoiceExtraData* data) void KnobChoice::onOriginalKnobPopulated() { - KnobSignalSlotHandler* handler = qobject_cast(sender()); - if (!handler) { - return; - } - boost::shared_ptr originalKnob = handler->getKnob(); - KnobChoice* isChoice = dynamic_cast(originalKnob.get()); + + KnobChoice* isChoice = dynamic_cast(sender()); if (!isChoice) { return; } @@ -876,16 +872,19 @@ void KnobChoice::handleSignalSlotsForAliasLink(const boost::shared_ptr& alias,bool connect) { assert(alias); - boost::shared_ptr handler = alias->getSignalSlotHandler(); + KnobChoice* aliasIsChoice = dynamic_cast(alias.get()); + if (!aliasIsChoice) { + return; + } if (connect) { - QObject::connect(_signalSlotHandler.get(), SIGNAL(populated()), handler.get(), SLOT(onOriginalKnobPopulated())); - QObject::connect(_signalSlotHandler.get(), SIGNAL(entriesReset()), handler.get(), SLOT(onOriginalKnobEntriesReset())); - QObject::connect(_signalSlotHandler.get(), SIGNAL(entryAppended(QString,QString)), handler.get(), + QObject::connect(this, SIGNAL(populated()), aliasIsChoice, SLOT(onOriginalKnobPopulated())); + QObject::connect(this, SIGNAL(entriesReset()), aliasIsChoice, SLOT(onOriginalKnobEntriesReset())); + QObject::connect(this, SIGNAL(entryAppended(QString,QString)), aliasIsChoice, SLOT(onOriginalKnobEntryAppend(QString,QString))); } else { - QObject::disconnect(_signalSlotHandler.get(), SIGNAL(populated()), handler.get(), SLOT(onOriginalKnobPopulated())); - QObject::disconnect(_signalSlotHandler.get(), SIGNAL(entriesReset()), handler.get(), SLOT(onOriginalKnobEntriesReset())); - QObject::disconnect(_signalSlotHandler.get(), SIGNAL(entryAppended(QString,QString)), handler.get(), + QObject::disconnect(this, SIGNAL(populated()), aliasIsChoice, SLOT(onOriginalKnobPopulated())); + QObject::disconnect(this, SIGNAL(entriesReset()), aliasIsChoice, SLOT(onOriginalKnobEntriesReset())); + QObject::disconnect(this, SIGNAL(entryAppended(QString,QString)), aliasIsChoice, SLOT(onOriginalKnobEntryAppend(QString,QString))); } } @@ -1146,36 +1145,38 @@ KnobGroup::removeKnob(KnobI* k) } } -void +bool KnobGroup::moveOneStepUp(KnobI* k) { for (U32 i = 0; i < _children.size(); ++i) { if (_children[i].lock().get() == k) { if (i == 0) { - break; + return false; } boost::weak_ptr tmp = _children[i - 1]; _children[i - 1] = _children[i]; _children[i] = tmp; - break; + return true; } } + throw std::invalid_argument("Given knob does not belong to this group"); } -void +bool KnobGroup::moveOneStepDown(KnobI* k) { for (U32 i = 0; i < _children.size(); ++i) { if (_children[i].lock().get() == k) { if (i == _children.size() - 1) { - break; + return false; } boost::weak_ptr tmp = _children[i + 1]; _children[i + 1] = _children[i]; _children[i] = tmp; - break; + return true; } } + throw std::invalid_argument("Given knob does not belong to this group"); } void @@ -1230,6 +1231,7 @@ KnobPage::KnobPage(KnobHolder* holder, bool declaredByPlugin) : Knob(holder, label, dimension, declaredByPlugin) { + setIsPersistant(false); } bool @@ -1335,36 +1337,38 @@ KnobPage::removeKnob(KnobI* k) } } -void +bool KnobPage::moveOneStepUp(KnobI* k) { for (U32 i = 0; i < _children.size(); ++i) { if (_children[i].lock().get() == k) { if (i == 0) { - break; + return false; } boost::weak_ptr tmp = _children[i - 1]; _children[i - 1] = _children[i]; _children[i] = tmp; - break; + return true; } } + throw std::invalid_argument("Given knob does not belong to this page"); } -void +bool KnobPage::moveOneStepDown(KnobI* k) { for (U32 i = 0; i < _children.size(); ++i) { if (_children[i].lock().get() == k) { if (i == _children.size() - 1) { - break; + return false; } boost::weak_ptr tmp = _children[i + 1]; _children[i + 1] = _children[i]; _children[i] = tmp; - break; + return true; } } + throw std::invalid_argument("Given knob does not belong to this page"); } diff --git a/Engine/KnobTypes.h b/Engine/KnobTypes.h index 0bb10c78a1..1530127cc6 100644 --- a/Engine/KnobTypes.h +++ b/Engine/KnobTypes.h @@ -459,6 +459,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON ValueChangedReturnCodeEnum setValueFromLabel(const std::string & value, int dimension, bool turnOffAutoKeying = false); + /// set the KnobChoice default value from the label void setDefaultValueFromLabel(const std::string & value,int dimension = 0); @@ -731,8 +732,8 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON void addKnob(boost::shared_ptr k); void removeKnob(KnobI* k); - void moveOneStepUp(KnobI* k); - void moveOneStepDown(KnobI* k); + bool moveOneStepUp(KnobI* k); + bool moveOneStepDown(KnobI* k); void insertKnob(int index, const boost::shared_ptr& k); @@ -781,8 +782,8 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON void addKnob(const boost::shared_ptr& k); - void moveOneStepUp(KnobI* k); - void moveOneStepDown(KnobI* k); + bool moveOneStepUp(KnobI* k); + bool moveOneStepDown(KnobI* k); void removeKnob(KnobI* k); diff --git a/Engine/Log.cpp b/Engine/Log.cpp index 80b444bbfd..92257da11f 100644 --- a/Engine/Log.cpp +++ b/Engine/Log.cpp @@ -34,9 +34,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include "Global/GlobalDefines.h" diff --git a/Engine/MergingEnum.h b/Engine/MergingEnum.h index 0fef4a589e..679817ee7b 100644 --- a/Engine/MergingEnum.h +++ b/Engine/MergingEnum.h @@ -1,6 +1,30 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * This file is part of Natron , + * Copyright (C) 2015 INRIA and Alexandre Gauthier-Foichat + * + * Natron is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Natron is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Natron. If not, see + * ***** END LICENSE BLOCK ***** */ + #ifndef MERGINGENUM_H #define MERGINGENUM_H +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + #include #include #include "Global/Enums.h" diff --git a/Engine/NatronEngine/effect_wrapper.cpp b/Engine/NatronEngine/effect_wrapper.cpp index b16346eef3..7b63a204ba 100644 --- a/Engine/NatronEngine/effect_wrapper.cpp +++ b/Engine/NatronEngine/effect_wrapper.cpp @@ -1142,6 +1142,48 @@ static PyObject* Sbk_EffectFunc_setLabel(PyObject* self, PyObject* pyArg) return 0; } +static PyObject* Sbk_EffectFunc_setPagesOrder(PyObject* self, PyObject* pyArg) +{ + ::Effect* cppSelf = 0; + SBK_UNUSED(cppSelf) + if (!Shiboken::Object::isValid(self)) + return 0; + cppSelf = ((::Effect*)Shiboken::Conversions::cppPointer(SbkNatronEngineTypes[SBK_EFFECT_IDX], (SbkObject*)self)); + int overloadId = -1; + PythonToCppFunc pythonToCpp; + SBK_UNUSED(pythonToCpp) + + // Overloaded function decisor + // 0: setPagesOrder(std::list) + if ((pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(SbkNatronEngineTypeConverters[SBK_NATRONENGINE_STD_LIST_STD_STRING_IDX], (pyArg)))) { + overloadId = 0; // setPagesOrder(std::list) + } + + // Function signature not found. + if (overloadId == -1) goto Sbk_EffectFunc_setPagesOrder_TypeError; + + // Call function/method + { + ::std::list cppArg0; + pythonToCpp(pyArg, &cppArg0); + + if (!PyErr_Occurred()) { + // setPagesOrder(std::list) + cppSelf->setPagesOrder(cppArg0); + } + } + + if (PyErr_Occurred()) { + return 0; + } + Py_RETURN_NONE; + + Sbk_EffectFunc_setPagesOrder_TypeError: + const char* overloads[] = {"list", 0}; + Shiboken::setErrorAboutWrongArguments(pyArg, "NatronEngine.Effect.setPagesOrder", overloads); + return 0; +} + static PyObject* Sbk_EffectFunc_setPosition(PyObject* self, PyObject* args) { ::Effect* cppSelf = 0; @@ -1373,6 +1415,7 @@ static PyMethodDef Sbk_Effect_methods[] = { {"isNodeSelected", (PyCFunction)Sbk_EffectFunc_isNodeSelected, METH_NOARGS}, {"setColor", (PyCFunction)Sbk_EffectFunc_setColor, METH_VARARGS}, {"setLabel", (PyCFunction)Sbk_EffectFunc_setLabel, METH_O}, + {"setPagesOrder", (PyCFunction)Sbk_EffectFunc_setPagesOrder, METH_O}, {"setPosition", (PyCFunction)Sbk_EffectFunc_setPosition, METH_VARARGS}, {"setScriptName", (PyCFunction)Sbk_EffectFunc_setScriptName, METH_O}, {"setSize", (PyCFunction)Sbk_EffectFunc_setSize, METH_VARARGS}, diff --git a/Engine/NatronEngine/natronengine_module_wrapper.cpp b/Engine/NatronEngine/natronengine_module_wrapper.cpp index 66febfe4de..1f06b45703 100644 --- a/Engine/NatronEngine/natronengine_module_wrapper.cpp +++ b/Engine/NatronEngine/natronengine_module_wrapper.cpp @@ -410,8 +410,8 @@ static PythonToCppFunc is_std_map_ImageLayer_EffectPTR__PythonToCpp_std_map_Imag return 0; } -// C++ to Python conversion for type 'std::list'. -static PyObject* std_list_std_string__CppToPython_std_list_std_string_(const void* cppIn) { +// C++ to Python conversion for type 'const std::list &'. +static PyObject* conststd_list_std_string_REF_CppToPython_conststd_list_std_string_REF(const void* cppIn) { ::std::list& cppInRef = *((::std::list*)cppIn); // TEMPLATE - stdListToPyList - START @@ -425,7 +425,7 @@ static PyObject* std_list_std_string__CppToPython_std_list_std_string_(const voi // TEMPLATE - stdListToPyList - END } -static void std_list_std_string__PythonToCpp_std_list_std_string_(PyObject* pyIn, void* cppOut) { +static void conststd_list_std_string_REF_PythonToCpp_conststd_list_std_string_REF(PyObject* pyIn, void* cppOut) { ::std::list& cppOutRef = *((::std::list*)cppOut); // TEMPLATE - pyListToStdList - START @@ -438,9 +438,9 @@ static void std_list_std_string__PythonToCpp_std_list_std_string_(PyObject* pyIn // TEMPLATE - pyListToStdList - END } -static PythonToCppFunc is_std_list_std_string__PythonToCpp_std_list_std_string__Convertible(PyObject* pyIn) { +static PythonToCppFunc is_conststd_list_std_string_REF_PythonToCpp_conststd_list_std_string_REF_Convertible(PyObject* pyIn) { if (Shiboken::Conversions::convertibleSequenceTypes(Shiboken::Conversions::PrimitiveTypeConverter(), pyIn)) - return std_list_std_string__PythonToCpp_std_list_std_string_; + return conststd_list_std_string_REF_PythonToCpp_conststd_list_std_string_REF; return 0; } @@ -716,12 +716,13 @@ SBK_MODULE_INIT_FUNCTION_BEGIN(NatronEngine) std_map_ImageLayer_EffectPTR__PythonToCpp_std_map_ImageLayer_EffectPTR_, is_std_map_ImageLayer_EffectPTR__PythonToCpp_std_map_ImageLayer_EffectPTR__Convertible); - // Register converter for type 'std::list'. - SbkNatronEngineTypeConverters[SBK_NATRONENGINE_STD_LIST_STD_STRING_IDX] = Shiboken::Conversions::createConverter(&PyList_Type, std_list_std_string__CppToPython_std_list_std_string_); + // Register converter for type 'const std::list&'. + SbkNatronEngineTypeConverters[SBK_NATRONENGINE_STD_LIST_STD_STRING_IDX] = Shiboken::Conversions::createConverter(&PyList_Type, conststd_list_std_string_REF_CppToPython_conststd_list_std_string_REF); + Shiboken::Conversions::registerConverterName(SbkNatronEngineTypeConverters[SBK_NATRONENGINE_STD_LIST_STD_STRING_IDX], "const std::list&"); Shiboken::Conversions::registerConverterName(SbkNatronEngineTypeConverters[SBK_NATRONENGINE_STD_LIST_STD_STRING_IDX], "std::list"); Shiboken::Conversions::addPythonToCppValueConversion(SbkNatronEngineTypeConverters[SBK_NATRONENGINE_STD_LIST_STD_STRING_IDX], - std_list_std_string__PythonToCpp_std_list_std_string_, - is_std_list_std_string__PythonToCpp_std_list_std_string__Convertible); + conststd_list_std_string_REF_PythonToCpp_conststd_list_std_string_REF, + is_conststd_list_std_string_REF_PythonToCpp_conststd_list_std_string_REF_Convertible); // Register converter for type 'QList'. SbkNatronEngineTypeConverters[SBK_NATRONENGINE_QLIST_QVARIANT_IDX] = Shiboken::Conversions::createConverter(&PyList_Type, _QList_QVariant__CppToPython__QList_QVariant_); diff --git a/Engine/NatronEngine/natronengine_python.h b/Engine/NatronEngine/natronengine_python.h index 105e5c0bec..08844cbd56 100644 --- a/Engine/NatronEngine/natronengine_python.h +++ b/Engine/NatronEngine/natronengine_python.h @@ -131,7 +131,7 @@ extern SbkConverter** SbkNatronEngineTypeConverters; #define SBK_NATRONENGINE_STD_LIST_EFFECTPTR_IDX 7 // std::list #define SBK_NATRONENGINE_STD_LIST_INT_IDX 8 // const std::list & #define SBK_NATRONENGINE_STD_MAP_IMAGELAYER_EFFECTPTR_IDX 9 // std::map -#define SBK_NATRONENGINE_STD_LIST_STD_STRING_IDX 10 // std::list +#define SBK_NATRONENGINE_STD_LIST_STD_STRING_IDX 10 // const std::list & #define SBK_NATRONENGINE_QLIST_QVARIANT_IDX 11 // QList #define SBK_NATRONENGINE_QLIST_QSTRING_IDX 12 // QList #define SBK_NATRONENGINE_QMAP_QSTRING_QVARIANT_IDX 13 // QMap diff --git a/Engine/NatronEngine/param_wrapper.cpp b/Engine/NatronEngine/param_wrapper.cpp index e8c86d9e1b..a22fe5d1c4 100644 --- a/Engine/NatronEngine/param_wrapper.cpp +++ b/Engine/NatronEngine/param_wrapper.cpp @@ -906,6 +906,53 @@ static PyObject* Sbk_ParamFunc_setAnimationEnabled(PyObject* self, PyObject* pyA return 0; } +static PyObject* Sbk_ParamFunc_setAsAlias(PyObject* self, PyObject* pyArg) +{ + ParamWrapper* cppSelf = 0; + SBK_UNUSED(cppSelf) + if (!Shiboken::Object::isValid(self)) + return 0; + cppSelf = (ParamWrapper*)((::Param*)Shiboken::Conversions::cppPointer(SbkNatronEngineTypes[SBK_PARAM_IDX], (SbkObject*)self)); + PyObject* pyResult = 0; + int overloadId = -1; + PythonToCppFunc pythonToCpp; + SBK_UNUSED(pythonToCpp) + + // Overloaded function decisor + // 0: setAsAlias(Param*) + if ((pythonToCpp = Shiboken::Conversions::isPythonToCppPointerConvertible((SbkObjectType*)SbkNatronEngineTypes[SBK_PARAM_IDX], (pyArg)))) { + overloadId = 0; // setAsAlias(Param*) + } + + // Function signature not found. + if (overloadId == -1) goto Sbk_ParamFunc_setAsAlias_TypeError; + + // Call function/method + { + if (!Shiboken::Object::isValid(pyArg)) + return 0; + ::Param* cppArg0; + pythonToCpp(pyArg, &cppArg0); + + if (!PyErr_Occurred()) { + // setAsAlias(Param*) + bool cppResult = cppSelf->setAsAlias(cppArg0); + pyResult = Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &cppResult); + } + } + + if (PyErr_Occurred() || !pyResult) { + Py_XDECREF(pyResult); + return 0; + } + return pyResult; + + Sbk_ParamFunc_setAsAlias_TypeError: + const char* overloads[] = {"NatronEngine.Param", 0}; + Shiboken::setErrorAboutWrongArguments(pyArg, "NatronEngine.Param.setAsAlias", overloads); + return 0; +} + static PyObject* Sbk_ParamFunc_setEnabled(PyObject* self, PyObject* args, PyObject* kwds) { ParamWrapper* cppSelf = 0; @@ -981,6 +1028,74 @@ static PyObject* Sbk_ParamFunc_setEnabled(PyObject* self, PyObject* args, PyObje return 0; } +static PyObject* Sbk_ParamFunc_setEnabledByDefault(PyObject* self, PyObject* args, PyObject* kwds) +{ + ParamWrapper* cppSelf = 0; + SBK_UNUSED(cppSelf) + if (!Shiboken::Object::isValid(self)) + return 0; + cppSelf = (ParamWrapper*)((::Param*)Shiboken::Conversions::cppPointer(SbkNatronEngineTypes[SBK_PARAM_IDX], (SbkObject*)self)); + int overloadId = -1; + PythonToCppFunc pythonToCpp[] = { 0 }; + SBK_UNUSED(pythonToCpp) + int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0); + int numArgs = PyTuple_GET_SIZE(args); + PyObject* pyArgs[] = {0}; + + // invalid argument lengths + if (numArgs + numNamedArgs > 1) { + PyErr_SetString(PyExc_TypeError, "NatronEngine.Param.setEnabledByDefault(): too many arguments"); + return 0; + } + + if (!PyArg_ParseTuple(args, "|O:setEnabledByDefault", &(pyArgs[0]))) + return 0; + + + // Overloaded function decisor + // 0: setEnabledByDefault(bool) + if (numArgs == 0) { + overloadId = 0; // setEnabledByDefault(bool) + } else if ((pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) { + overloadId = 0; // setEnabledByDefault(bool) + } + + // Function signature not found. + if (overloadId == -1) goto Sbk_ParamFunc_setEnabledByDefault_TypeError; + + // Call function/method + { + if (kwds) { + PyObject* value = PyDict_GetItemString(kwds, "enabled"); + if (value && pyArgs[0]) { + PyErr_SetString(PyExc_TypeError, "NatronEngine.Param.setEnabledByDefault(): got multiple values for keyword argument 'enabled'."); + return 0; + } else if (value) { + pyArgs[0] = value; + if (!(pythonToCpp[0] = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArgs[0])))) + goto Sbk_ParamFunc_setEnabledByDefault_TypeError; + } + } + bool cppArg0 = 0; + if (pythonToCpp[0]) pythonToCpp[0](pyArgs[0], &cppArg0); + + if (!PyErr_Occurred()) { + // setEnabledByDefault(bool) + cppSelf->setEnabledByDefault(cppArg0); + } + } + + if (PyErr_Occurred()) { + return 0; + } + Py_RETURN_NONE; + + Sbk_ParamFunc_setEnabledByDefault_TypeError: + const char* overloads[] = {"bool = 0", 0}; + Shiboken::setErrorAboutWrongArguments(args, "NatronEngine.Param.setEnabledByDefault", overloads); + return 0; +} + static PyObject* Sbk_ParamFunc_setEvaluateOnChange(PyObject* self, PyObject* pyArg) { ParamWrapper* cppSelf = 0; @@ -1149,6 +1264,48 @@ static PyObject* Sbk_ParamFunc_setVisible(PyObject* self, PyObject* pyArg) return 0; } +static PyObject* Sbk_ParamFunc_setVisibleByDefault(PyObject* self, PyObject* pyArg) +{ + ParamWrapper* cppSelf = 0; + SBK_UNUSED(cppSelf) + if (!Shiboken::Object::isValid(self)) + return 0; + cppSelf = (ParamWrapper*)((::Param*)Shiboken::Conversions::cppPointer(SbkNatronEngineTypes[SBK_PARAM_IDX], (SbkObject*)self)); + int overloadId = -1; + PythonToCppFunc pythonToCpp; + SBK_UNUSED(pythonToCpp) + + // Overloaded function decisor + // 0: setVisibleByDefault(bool) + if ((pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(Shiboken::Conversions::PrimitiveTypeConverter(), (pyArg)))) { + overloadId = 0; // setVisibleByDefault(bool) + } + + // Function signature not found. + if (overloadId == -1) goto Sbk_ParamFunc_setVisibleByDefault_TypeError; + + // Call function/method + { + bool cppArg0; + pythonToCpp(pyArg, &cppArg0); + + if (!PyErr_Occurred()) { + // setVisibleByDefault(bool) + cppSelf->setVisibleByDefault(cppArg0); + } + } + + if (PyErr_Occurred()) { + return 0; + } + Py_RETURN_NONE; + + Sbk_ParamFunc_setVisibleByDefault_TypeError: + const char* overloads[] = {"bool", 0}; + Shiboken::setErrorAboutWrongArguments(pyArg, "NatronEngine.Param.setVisibleByDefault", overloads); + return 0; +} + static PyMethodDef Sbk_Param_methods[] = { {"_addAsDependencyOf", (PyCFunction)Sbk_ParamFunc__addAsDependencyOf, METH_VARARGS}, {"copy", (PyCFunction)Sbk_ParamFunc_copy, METH_VARARGS|METH_KEYWORDS}, @@ -1170,11 +1327,14 @@ static PyMethodDef Sbk_Param_methods[] = { {"randomInt", (PyCFunction)Sbk_ParamFunc_randomInt, METH_VARARGS}, {"setAddNewLine", (PyCFunction)Sbk_ParamFunc_setAddNewLine, METH_O}, {"setAnimationEnabled", (PyCFunction)Sbk_ParamFunc_setAnimationEnabled, METH_O}, + {"setAsAlias", (PyCFunction)Sbk_ParamFunc_setAsAlias, METH_O}, {"setEnabled", (PyCFunction)Sbk_ParamFunc_setEnabled, METH_VARARGS|METH_KEYWORDS}, + {"setEnabledByDefault", (PyCFunction)Sbk_ParamFunc_setEnabledByDefault, METH_VARARGS|METH_KEYWORDS}, {"setEvaluateOnChange", (PyCFunction)Sbk_ParamFunc_setEvaluateOnChange, METH_O}, {"setHelp", (PyCFunction)Sbk_ParamFunc_setHelp, METH_O}, {"setPersistant", (PyCFunction)Sbk_ParamFunc_setPersistant, METH_O}, {"setVisible", (PyCFunction)Sbk_ParamFunc_setVisible, METH_O}, + {"setVisibleByDefault", (PyCFunction)Sbk_ParamFunc_setVisibleByDefault, METH_O}, {0} // Sentinel }; diff --git a/Engine/NoOpBase.cpp b/Engine/NoOpBase.cpp index d14fad23f3..6f064ea125 100644 --- a/Engine/NoOpBase.cpp +++ b/Engine/NoOpBase.cpp @@ -100,3 +100,13 @@ NoOpBase::getInputsHoldingTransform(std::list* inputs) const inputs->push_back(0); return true; } + +Natron::ImagePremultiplicationEnum +NoOpBase::getOutputPremultiplication() const +{ + Natron::EffectInstance* input = getInput(0); + if (input) { + return input->getOutputPremultiplication(); + } + return Natron::eImagePremultiplicationPremultiplied; +} diff --git a/Engine/NoOpBase.h b/Engine/NoOpBase.h index 92f81bebaf..06fa850fc8 100644 --- a/Engine/NoOpBase.h +++ b/Engine/NoOpBase.h @@ -98,7 +98,8 @@ class NoOpBase virtual bool isHostChannelSelectorSupported(bool* defaultR,bool* defaultG, bool* defaultB, bool* defaultA) const OVERRIDE FINAL; - + + virtual Natron::ImagePremultiplicationEnum getOutputPremultiplication() const OVERRIDE WARN_UNUSED_RETURN; private: /** diff --git a/Engine/Node.cpp b/Engine/Node.cpp index 6b6dc382da..73f4af8cdb 100644 --- a/Engine/Node.cpp +++ b/Engine/Node.cpp @@ -288,14 +288,7 @@ struct Node::Implementation , mustComputeInputRelatedData(true) , duringPaintStrokeCreation(false) , lastStrokeMovementMutex() - , lastStrokeMovementBbox() , strokeBitmapCleared(false) - , lastStrokeIndex(-1) - , multiStrokeIndex(0) - , strokeImage() - , lastStrokePoints() - , distToNextIn(0.) - , distToNextOut(0.) , useAlpha0ToConvertFromRGBToRGBA(false) , isBeingDestroyed(false) , inputModifiedRecursion(0) @@ -514,12 +507,8 @@ struct Node::Implementation bool duringPaintStrokeCreation; // protected by lastStrokeMovementMutex mutable QMutex lastStrokeMovementMutex; - RectD lastStrokeMovementBbox; bool strokeBitmapCleared; - int lastStrokeIndex,multiStrokeIndex; - ImagePtr strokeImage; - std::list > lastStrokePoints; - double distToNextIn,distToNextOut; + //This flag is used for the Roto plug-in and for the Merge inside the rotopaint tree //so that if the input of the roto node is RGB, it gets converted with alpha = 0, otherwise the user @@ -540,6 +529,9 @@ struct Node::Implementation }; + + + /** *@brief Actually converting to ARGB... but it is called BGRA by the texture format GL_UNSIGNED_INT_8_8_8_8_REV @@ -729,11 +721,19 @@ Node::load(const std::string & parentMultiInstanceName, } else { pluginLabel = _imp->plugin->getPluginLabel(); } - getGroup()->initNodeName(isMultiInstanceChild ? parentMultiInstanceName + '_' : pluginLabel.toStdString(),&name); - setNameInternal(name.c_str()); + try { + getGroup()->initNodeName(isMultiInstanceChild ? parentMultiInstanceName + '_' : pluginLabel.toStdString(),&name); + } catch (...) { + + } + setNameInternal(name.c_str(), false); nameSet = true; } else { - setScriptName(fixedName.toStdString()); + try { + setScriptName(fixedName.toStdString()); + } catch (...) { + appPTR->writeToOfxLog_mt_safe("Could not set node name to " + fixedName); + } } if (!isMultiInstanceChild && _imp->isMultiInstance) { updateEffectLabelKnob( getScriptName().c_str() ); @@ -812,13 +812,8 @@ Node::usesAlpha0ToConvertFromRGBToRGBA() const void Node::setWhileCreatingPaintStroke(bool creating) { - { - QMutexLocker k(&_imp->lastStrokeMovementMutex); - _imp->duringPaintStrokeCreation = creating; - if (creating) { - _imp->lastStrokeIndex = -1; - } - } + QMutexLocker k(&_imp->lastStrokeMovementMutex); + _imp->duringPaintStrokeCreation = creating; } bool @@ -903,29 +898,21 @@ Node::refreshDynamicProperties() } void -Node::updateLastPaintStrokeData(int newAge,const std::list >& points, - const RectD& lastPointsBbox, - int strokeIndex) +Node::prepareForNextPaintStrokeRender() { { QMutexLocker k(&_imp->lastStrokeMovementMutex); - _imp->lastStrokePoints = points; - _imp->lastStrokeMovementBbox = lastPointsBbox; - _imp->lastStrokeIndex = newAge; - _imp->distToNextIn = _imp->distToNextOut; _imp->strokeBitmapCleared = false; - _imp->multiStrokeIndex = strokeIndex; } _imp->liveInstance->clearActionsCache(); } void -Node::setLastPaintStrokeDataNoRotopaint(const RectD& lastStrokeBbox) +Node::setLastPaintStrokeDataNoRotopaint() { { QMutexLocker k(&_imp->lastStrokeMovementMutex); - _imp->lastStrokeMovementBbox = lastStrokeBbox; _imp->strokeBitmapCleared = false; _imp->duringPaintStrokeCreation = true; } @@ -937,7 +924,6 @@ Node::invalidateLastPaintStrokeDataNoRotopaint() { { QMutexLocker k(&_imp->lastStrokeMovementMutex); - _imp->lastStrokeMovementBbox.clear(); _imp->duringPaintStrokeCreation = false; } @@ -960,7 +946,6 @@ Node::getPaintStrokeRoD(double time, RectD* bbox) const *bbox = getPaintStrokeRoD_duringPainting(); } else { boost::shared_ptr stroke = _imp->paintStroke.lock(); - assert(stroke); if (!stroke) { throw std::logic_error(""); } @@ -969,13 +954,7 @@ Node::getPaintStrokeRoD(double time, RectD* bbox) const } -void -Node::getLastPaintStrokeRoD(RectD* bbox) -{ - QMutexLocker k(&_imp->lastStrokeMovementMutex); - *bbox = _imp->lastStrokeMovementBbox; - -} + bool Node::isLastPaintStrokeBitmapCleared() const @@ -997,10 +976,13 @@ Node::getLastPaintStrokePoints(double time, std::list > >* strokes, int* strokeIndex) const { - QMutexLocker k(&_imp->lastStrokeMovementMutex); - if (_imp->duringPaintStrokeCreation) { - strokes->push_back(_imp->lastStrokePoints); - *strokeIndex = _imp->multiStrokeIndex; + bool duringPaintStroke; + { + QMutexLocker k(&_imp->lastStrokeMovementMutex); + duringPaintStroke = _imp->duringPaintStrokeCreation; + } + if (duringPaintStroke) { + getApp()->getLastPaintStrokePoints(strokes, strokeIndex); } else { boost::shared_ptr item = _imp->paintStroke.lock(); RotoStrokeItem* stroke = dynamic_cast(item.get()); @@ -1013,26 +995,6 @@ Node::getLastPaintStrokePoints(double time, } } -bool -Node::isFirstPaintStrokeRenderTick() const -{ - QMutexLocker k(&_imp->lastStrokeMovementMutex); - return _imp->lastStrokeIndex == -1; -} - -int -Node::getStrokeImageAge() const -{ - QMutexLocker k(&_imp->lastStrokeMovementMutex); - return _imp->lastStrokeIndex; -} - -void -Node::updateStrokeImage(const boost::shared_ptr& image) -{ - QMutexLocker k(&_imp->lastStrokeMovementMutex); - _imp->strokeImage = image; -} boost::shared_ptr Node::getOrRenderLastStrokeImage(unsigned int mipMapLevel, @@ -1053,9 +1015,17 @@ Node::getOrRenderLastStrokeImage(unsigned int mipMapLevel, } // qDebug() << getScriptName_mt_safe().c_str() << "Rendering stroke: " << _imp->lastStrokeMovementBbox.x1 << _imp->lastStrokeMovementBbox.y1 << _imp->lastStrokeMovementBbox.x2 << _imp->lastStrokeMovementBbox.y2; - _imp->distToNextOut = stroke->renderSingleStroke(stroke, _imp->lastStrokeMovementBbox, _imp->lastStrokePoints, mipMapLevel, par, components, depth, _imp->distToNextIn, &_imp->strokeImage); + + RectD lastStrokeBbox; + std::list > lastStrokePoints; + double distNextIn; + boost::shared_ptr strokeImage; + getApp()->getRenderStrokeData(&lastStrokeBbox, &lastStrokePoints, &distNextIn, &strokeImage); + double distToNextOut = stroke->renderSingleStroke(stroke, lastStrokeBbox, lastStrokePoints, mipMapLevel, par, components, depth, distNextIn, &strokeImage); - return _imp->strokeImage; + getApp()->updateStrokeImage(strokeImage, distToNextOut, true); + + return strokeImage; } bool @@ -1090,9 +1060,10 @@ Node::declareRotoPythonField() { assert(_imp->rotoContext); std::string appID = getApp()->getAppIDString(); - std::string fullyQualifiedName = appID + "." + getFullyQualifiedName(); + std::string nodeName = getFullyQualifiedName(); + std::string nodeFullName = appID + "." + nodeName; std::string err; - std::string script = fullyQualifiedName + ".roto = " + fullyQualifiedName + ".getRotoContext()\n"; + std::string script = nodeFullName + ".roto = " + nodeFullName + ".getRotoContext()\n"; if (!appPTR->isBackground()) { getApp()->printAutoDeclaredVariable(script); } @@ -1313,7 +1284,7 @@ Node::computeHashInternal(std::list& marked) ///If the node is a group, call it on all nodes in the group ///Also force a change to their hash - NodeGroup* group = dynamic_cast(getLiveInstance()); + /*NodeGroup* group = dynamic_cast(getLiveInstance()); if (group) { NodeList nodes = group->getNodes(); for (NodeList::iterator it = nodes.begin(); it != nodes.end(); ++it) { @@ -1322,7 +1293,7 @@ Node::computeHashInternal(std::list& marked) (*it)->computeHashInternal(marked); } } - +*/ } void @@ -1552,16 +1523,53 @@ Node::restoreKnobsLinks(const NodeSerialization & serialization, } const std::list >& userKnobs = serialization.getUserPages(); - for (std::list >::const_iterator it = userKnobs.begin(); it != userKnobs.end(); ++it) { - _imp->restoreKnobLinksRecursive(it->get(), allNodes); + for (std::list >::const_iterator it = userKnobs.begin(); it != userKnobs.end(); ++it) { + _imp->restoreKnobLinksRecursive((*it).get(), allNodes); } } +void +Node::setPagesOrder(const std::list& pages) +{ + //re-order the pages + std::list > pagesOrdered; + + for (std::list::const_iterator it = pages.begin(); it!=pages.end();++it) { + const std::vector > &knobs = getKnobs(); + for (std::vector >::const_iterator it2 = knobs.begin(); it2 != knobs.end(); ++it2) { + if ((*it2)->getName() == *it) { + pagesOrdered.push_back(*it2); + _imp->liveInstance->removeKnobFromList(it2->get()); + break; + } + } + } + int index = 0; + for (std::list >::iterator it= pagesOrdered.begin() ;it!=pagesOrdered.end(); ++it,++index) { + _imp->liveInstance->insertKnob(index, *it); + } +} + +std::list +Node::getPagesOrder() const +{ + const std::vector >& knobs = getKnobs(); + std::list ret; + for (std::vector >::const_iterator it = knobs.begin(); it!=knobs.end(); ++it) { + KnobPage* ispage = dynamic_cast(it->get()); + if (ispage) { + ret.push_back(ispage->getName()); + } + } + return ret; +} + void Node::restoreUserKnobs(const NodeSerialization& serialization) { const std::list >& userPages = serialization.getUserPages(); + for (std::list >::const_iterator it = userPages.begin() ; it != userPages.end(); ++it) { boost::shared_ptr found = getKnobByName((*it)->getName()); boost::shared_ptr page; @@ -1569,14 +1577,16 @@ Node::restoreUserKnobs(const NodeSerialization& serialization) page = Natron::createKnob(_imp->liveInstance.get(), (*it)->getLabel() , 1, false); page->setAsUserKnob(); page->setName((*it)->getName()); + } else { page = boost::dynamic_pointer_cast(found); } if (page) { _imp->restoreUserKnobsRecursive((*it)->getChildren(), boost::shared_ptr(), page); } - } + setPagesOrder(serialization.getPagesOrdered()); + } void @@ -2292,9 +2302,9 @@ static void prependGroupNameRecursive(const boost::shared_ptr& gro } std::string -Node::getFullyQualifiedName() const +Node::getFullyQualifiedNameInternal(const std::string& scriptName) const { - std::string ret = getScriptName_mt_safe(); + std::string ret = scriptName; NodePtr parent = getParentMultiInstance(); if (parent) { prependGroupNameRecursive(parent, ret); @@ -2306,6 +2316,13 @@ Node::getFullyQualifiedName() const } } return ret; + +} + +std::string +Node::getFullyQualifiedName() const +{ + return getFullyQualifiedNameInternal(getScriptName_mt_safe()); } void @@ -2349,12 +2366,12 @@ Node::getLabel_mt_safe() const void Node::setScriptName_no_error_check(const std::string & name) { - setNameInternal(name); + setNameInternal(name, false); } void -Node::setNameInternal(const std::string& name) +Node::setNameInternal(const std::string& name, bool throwErrors) { std::string oldName = getScriptName_mt_safe(); std::string fullOldName = getFullyQualifiedName(); @@ -2362,7 +2379,42 @@ Node::setNameInternal(const std::string& name) boost::shared_ptr collection = getGroup(); if (collection) { - collection->setNodeName(name,false, false, &newName); + if (throwErrors) { + try { + collection->setNodeName(name,false, false, &newName); + } catch (const std::exception& e) { + appPTR->writeToOfxLog_mt_safe(e.what()); + std::cerr << e.what() << std::endl; + return; + } + } else { + collection->setNodeName(name,false, false, &newName); + } + } + + + + if (oldName == newName) { + return; + } + + + if (!newName.empty()) { + bool isAttrDefined = false; + std::string newPotentialQualifiedName = getApp()->getAppIDString() + getFullyQualifiedNameInternal(newName); + (void)Natron::getAttrRecursive(newPotentialQualifiedName, appPTR->getMainModule(), &isAttrDefined); + if (isAttrDefined) { + std::stringstream ss; + ss << "A Python attribute with the same name (" << newPotentialQualifiedName << ") already exists."; + if (throwErrors) { + throw std::runtime_error(ss.str()); + } else { + std::string err = ss.str(); + appPTR->writeToOfxLog_mt_safe(err.c_str()); + std::cerr << err << std::endl; + return; + } + } } bool mustSetCacheID; @@ -2400,31 +2452,6 @@ Node::setNameInternal(const std::string& name) } catch (const std::exception& e) { qDebug() << e.what(); } - - const std::vector > & knobs = getKnobs(); - - for (U32 i = 0; i < knobs.size(); ++i) { - std::list > listeners; - knobs[i]->getListeners(listeners); - ///For all listeners make sure they belong to a node - bool foundEffect = false; - for (std::list >::iterator it2 = listeners.begin(); it2 != listeners.end(); ++it2) { - EffectInstance* isEffect = dynamic_cast( (*it2)->getHolder() ); - if ( isEffect && ( isEffect != _imp->liveInstance.get() ) && isEffect->getNode()->isActivated() ) { - foundEffect = true; - break; - } - } - if (foundEffect) { - Natron::warningDialog( tr("Rename").toStdString(), tr("This node has one or several " - "parameters from which other parameters " - "of the project rely on through expressions " - "or links. Changing the name of this node will probably " - "break these expressions. You should carefully update them. ") - .toStdString() ); - break; - } - } } } else { //if (!oldName.empty()) { declareNodeVariableToPython(fullySpecifiedName); @@ -2436,25 +2463,23 @@ Node::setNameInternal(const std::string& name) Q_EMIT labelChanged(qnewName); } -bool +void Node::setScriptName(const std::string& name) { std::string newName; if (getGroup()) { - if (!getGroup()->setNodeName(name,false, true, &newName)) { - return false; - } + getGroup()->setNodeName(name,false, true, &newName); } else { newName = name; } //We do not allow setting the script-name of output nodes because we rely on it with NatronRenderer if (dynamic_cast(_imp->liveInstance.get())) { - return false; + throw std::runtime_error(QObject::tr("Changing the script-name of an Output node is not a valid operation").toStdString()); + return; } - setNameInternal(newName); - return true; + setNameInternal(newName, true); } @@ -2689,8 +2714,13 @@ Node::initializeKnobs(int renderScaleSupportPref) if (useSelectors) { - boost::shared_ptr sep = Natron::createKnob(_imp->liveInstance.get(), "Advanced", 1, false); - mainPage->addKnob(sep); + std::vector > mainPageChildren = mainPage->getChildren(); + bool skipSeparator = !mainPageChildren.empty() && dynamic_cast(mainPageChildren.back().get()); + + if (skipSeparator) { + boost::shared_ptr sep = Natron::createKnob(_imp->liveInstance.get(), "Advanced", 1, false); + mainPage->addKnob(sep); + } ///Create input layer selectors for (int i = 0; i < inputsCount; ++i) { @@ -2834,6 +2864,7 @@ Node::initializeKnobs(int renderScaleSupportPref) boost::shared_ptr channelName = Natron::createKnob(_imp->liveInstance.get(), "",1,false); channelName->setSecretByDefault(true); channelName->setEvaluateOnChange(false); + channelName->setDefaultValue(choices[choices.size() - 1]); if (mainPage) { mainPage->addKnob(channelName); } @@ -3145,20 +3176,24 @@ Node::Implementation::createChannelSelector(int inputNb,const std::string & inpu baseLayers.push_back(ImageComponents::getForwardMotionComponents().getLayerName()); baseLayers.push_back(ImageComponents::getBackwardMotionComponents().getLayerName()); layer->populateChoices(baseLayers); + int defVal; if (isOutput && liveInstance->isPassThroughForNonRenderedPlanes() == EffectInstance::ePassThroughRenderAllRequestedPlanes) { - layer->setDefaultValue(0); + defVal = 0; + //Hide all other input selectors if choice is All in output for (std::map::iterator it = channelsSelectors.begin(); it!=channelsSelectors.end(); ++it) { it->second.layer.lock()->setSecret(true); } } else { - layer->setDefaultValue(1); + defVal = 1; } + layer->setDefaultValue(defVal); boost::shared_ptr layerName = Natron::createKnob(liveInstance.get(), inputName + "_layer_name", 1, false); layerName->setSecretByDefault(true); layerName->setAnimationEnabled(false); layerName->setEvaluateOnChange(false); + layerName->setDefaultValue(baseLayers[defVal]); //layerName->setAddNewLine(!sel.useRGBASelectors); page->addKnob(layerName); sel.layerName = layerName; @@ -4263,7 +4298,6 @@ void Node::clearLastRenderedImage() { _imp->liveInstance->clearLastRenderedImage(); - _imp->strokeImage.reset(); } /*After this call this node still knows the link to the old inputs/outputs @@ -4739,8 +4773,7 @@ Node::makePreviewImage(SequenceTime time, return false; } - ParallelRenderArgsSetter frameRenderArgs(getApp()->getProject().get(), - time, + ParallelRenderArgsSetter frameRenderArgs(time, 0, //< preview only renders view 0 (left) true, //getTimeLine()->currentFrame(); - ParallelRenderArgsSetter frameRenderArgs(getApp()->getProject().get(), - time, + ParallelRenderArgsSetter frameRenderArgs(time, 0 /*view*/, true, false, @@ -6120,7 +6152,7 @@ Node::refreshCreatedViews(KnobI* knob) std::string filename = inputFileKnob->getValue(); std::stringstream ss; - for (std::size_t i = 0; i < missingViews.size(); ++i) { + for (int i = 0; i < missingViews.size(); ++i) { ss << missingViews[i].toStdString(); if (i < missingViews.size() - 1) { ss << ", "; @@ -6458,7 +6490,7 @@ Node::refreshEnabledKnobsLabel(const Natron::ImageComponents& comp) enabled->setSecret(false); enabled->setLabel(channels[i]); } - enabled->setValue(true, 0); + //enabled->setValue(true, 0); } } @@ -6817,6 +6849,8 @@ Node::canOthersConnectToThisNode() const return false; } else if (dynamic_cast(_imp->liveInstance.get())) { return false; + } else if (_imp->liveInstance->isWriter() && _imp->liveInstance->getSequentialPreference() == Natron::eSequentialPreferenceOnlySequential) { + return false; } ///In debug mode only allow connections to Writer nodes # ifdef DEBUG @@ -7642,41 +7676,6 @@ Node::getAttachedRotoItem() const return _imp->paintStroke.lock(); } -/** - * @brief Given a fullyQualifiedName, e.g: app1.Group1.Blur1 - * this function returns the PyObject attribute of Blur1 if it is defined, or Group1 otherwise - * If app1 or Group1 does not exist at this point, this is a failure. - **/ -static PyObject* getAttrRecursive(const std::string& fullyQualifiedName,PyObject* parentObj,bool* isDefined) -{ - std::size_t foundDot = fullyQualifiedName.find("."); - std::string attrName = foundDot == std::string::npos ? fullyQualifiedName : fullyQualifiedName.substr(0, foundDot); - PyObject* obj = 0; - if (PyObject_HasAttrString(parentObj, attrName.c_str())) { - obj = PyObject_GetAttrString(parentObj, attrName.c_str()); - } - - ///We either found the parent object or we are on the last object in which case we return the parent - if (!obj) { - assert(fullyQualifiedName.find(".") == std::string::npos); - *isDefined = false; - return parentObj; - } else { - assert(obj); - std::string recurseName; - if (foundDot != std::string::npos) { - recurseName = fullyQualifiedName; - recurseName.erase(0, foundDot + 1); - } - if (!recurseName.empty()) { - return getAttrRecursive(recurseName, obj, isDefined); - } else { - *isDefined = true; - return obj; - } - } - -} void @@ -7695,14 +7694,14 @@ Node::declareNodeVariableToPython(const std::string& nodeName) std::string appID = getApp()->getAppIDString(); - std::string varName = appID + "." + nodeName; + std::string nodeFullName = appID + "." + nodeName; bool alreadyDefined = false; - PyObject* nodeObj = getAttrRecursive(varName, mainModule, &alreadyDefined); + PyObject* nodeObj = Natron::getAttrRecursive(nodeFullName, mainModule, &alreadyDefined); assert(nodeObj); Q_UNUSED(nodeObj); if (!alreadyDefined) { - std::string script = varName + " = " + appID + ".getNode(\""; + std::string script = nodeFullName + " = " + appID + ".getNode(\""; script.append(nodeName); script.append("\")\n"); std::string err; @@ -7774,13 +7773,13 @@ Node::declarePythonFields() } std::locale locale; - std::string fullName = getFullyQualifiedName(); + std::string nodeName = getFullyQualifiedName(); std::string appID = getApp()->getAppIDString(); bool alreadyDefined = false; - std::string nodeFullName = appID + "." + fullName; - PyObject* nodeObj = getAttrRecursive(nodeFullName, getMainModule(), &alreadyDefined); + std::string nodeFullName = appID + "." + nodeName; + PyObject* nodeObj = Natron::getAttrRecursive(nodeFullName, getMainModule(), &alreadyDefined); assert(nodeObj); Q_UNUSED(nodeObj); if (!alreadyDefined) { @@ -7807,11 +7806,11 @@ Node::removeParameterFromPython(const std::string& parameterName) } Natron::PythonGILLocker pgl; std::string appID = getApp()->getAppIDString(); - std::string fullName = getFullyQualifiedName(); - std::string nodeFullName = appID + "." + fullName; + std::string nodeName = getFullyQualifiedName(); + std::string nodeFullName = appID + "." + nodeName; bool alreadyDefined = false; - PyObject* nodeObj = getAttrRecursive(nodeFullName, getMainModule(), &alreadyDefined); + PyObject* nodeObj = Natron::getAttrRecursive(nodeFullName, getMainModule(), &alreadyDefined); assert(nodeObj); Q_UNUSED(nodeObj); if (!alreadyDefined) { @@ -8097,7 +8096,9 @@ Node::Implementation::runInputChangedCallback(int index,const std::string& cb) std::string thisGroupVar; NodeGroup* isParentGrp = dynamic_cast(collection.get()); if (isParentGrp) { - thisGroupVar = appID + "." + isParentGrp->getNode()->getFullyQualifiedName(); + std::string nodeName = isParentGrp->getNode()->getFullyQualifiedName(); + std::string nodeFullName = appID + "." + nodeName; + thisGroupVar = nodeFullName; } else { thisGroupVar = appID; } diff --git a/Engine/Node.h b/Engine/Node.h index 6f5ade4c4f..f5456e5378 100644 --- a/Engine/Node.h +++ b/Engine/Node.h @@ -163,6 +163,10 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON void restoreUserKnobs(const NodeSerialization& serialization); + void setPagesOrder(const std::list& pages); + + std::list getPagesOrder() const; + bool isNodeCreated() const; /*@brief Quit all processing done by all render instances of this node @@ -415,21 +419,16 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON /////////////////////ROTO-PAINT related functionnalities////////////////////// ////////////////////////////////////////////////////////////////////////////// - void updateLastPaintStrokeData(int newAge,const std::list >& points, - const RectD& lastPointsBbox, - int strokeIndex); + + void prepareForNextPaintStrokeRender(); //Used by nodes below the rotopaint tree to optimize the RoI - void setLastPaintStrokeDataNoRotopaint(const RectD& lastStrokeBbox); + void setLastPaintStrokeDataNoRotopaint(); void invalidateLastPaintStrokeDataNoRotopaint(); void getPaintStrokeRoD(double time,RectD* bbox) const; RectD getPaintStrokeRoD_duringPainting() const; - bool isFirstPaintStrokeRenderTick() const; - int getStrokeImageAge() const; - void updateStrokeImage(const boost::shared_ptr& image); - void getLastPaintStrokeRoD(RectD* pointsBbox) ; bool isLastPaintStrokeBitmapCleared() const; void clearLastPaintStrokeRoD(); void getLastPaintStrokePoints(double time,std::list > >* strokes, int* strokeIndex) const; @@ -933,9 +932,9 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON /** * @brief Set the node name. - * @returns True upon success, false otherwise. An error dialog will be displayed upon error. + * Throws a run-time error with the message in case of error **/ - bool setScriptName(const std::string & name); + void setScriptName(const std::string & name); void setScriptName_no_error_check(const std::string & name); @@ -1097,7 +1096,9 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON bool refreshDraftFlagInternal(const std::vector >& inputs); - void setNameInternal(const std::string& name); + void setNameInternal(const std::string& name, bool throwErrors); + + std::string getFullyQualifiedNameInternal(const std::string& scriptName) const; void s_outputLayerChanged() { Q_EMIT outputLayerChanged(); } diff --git a/Engine/NodeGroup.cpp b/Engine/NodeGroup.cpp index 1945f4594d..af26a287f4 100644 --- a/Engine/NodeGroup.cpp +++ b/Engine/NodeGroup.cpp @@ -55,7 +55,7 @@ #include "Engine/TimeLine.h" #include "Engine/ViewerInstance.h" -#define NATRON_PYPLUG_EXPORTER_VERSION 2 +#define NATRON_PYPLUG_EXPORTER_VERSION 3 using namespace Natron; @@ -435,18 +435,36 @@ NodeCollection::clearNodes(bool emitSignal) } -bool +void NodeCollection::setNodeName(const std::string& baseName,bool appendDigit,bool errorIfExists,std::string* nodeName) { if (baseName.empty()) { - return false; + throw std::runtime_error(QObject::tr("Invalid script-name").toStdString()); + return; } ///Remove any non alpha-numeric characters from the baseName std::string cpy = Natron::makeNameScriptFriendly(baseName); if (cpy.empty()) { - return false; + throw std::runtime_error(QObject::tr("Invalid script-name").toStdString()); + return; } + ///If this is a group and one of its parameter has the same script-name as the script-name of one of the node inside + ///the python attribute will be overwritten. Try to prevent this situation. + NodeGroup* isGroup = dynamic_cast(this); + if (isGroup) { + const std::vector >& knobs = isGroup->getKnobs(); + for (std::vector >::const_iterator it = knobs.begin(); it != knobs.end(); ++it) { + if ((*it)->getName() == cpy) { + std::stringstream ss; + ss << QObject::tr("A node within a group cannot have the same script-name (").toStdString(); + ss << cpy; + ss << QObject::tr(") as a parameter on the group for scripting purposes.").toStdString(); + throw std::runtime_error(ss.str()); + return; + } + } + } bool foundNodeWithName = false; int no = 1; @@ -469,7 +487,12 @@ NodeCollection::setNodeName(const std::string& baseName,bool appendDigit,bool er } if (foundNodeWithName) { if (errorIfExists || !appendDigit) { - return false; + std::stringstream ss; + ss << QObject::tr("A node with the script-name ").toStdString(); + ss << *nodeName; + ss << QObject::tr(" already exists").toStdString(); + throw std::runtime_error(ss.str()); + return; } ++no; { @@ -479,7 +502,6 @@ NodeCollection::setNodeName(const std::string& baseName,bool appendDigit,bool er } } } while (foundNodeWithName); - return true; } void @@ -493,9 +515,8 @@ NodeCollection::initNodeName(const std::string& pluginLabel,std::string* nodeNam baseName = baseName.substr(0,baseName.size() - 3); } - if (!setNodeName(baseName,true, false, nodeName)) { - throw std::invalid_argument(QObject::tr("Invalid plugin label: ").toStdString() + pluginLabel); - } + setNodeName(baseName,true, false, nodeName); + } bool @@ -940,166 +961,6 @@ NodeCollection::forceComputeInputDependentDataOnAllTrees() } - - - -void -NodeCollection::setParallelRenderArgs(double time, - int view, - bool isRenderUserInteraction, - bool isSequential, - bool canAbort, - U64 renderAge, - const boost::shared_ptr& treeRoot, - const FrameRequestMap* request, - int textureIndex, - const TimeLine* timeline, - const boost::shared_ptr& activeRotoPaintNode, - bool isAnalysis, - bool draftMode, - bool viewerProgressReportEnabled, - const boost::shared_ptr& stats) -{ - - bool doNanHandling = appPTR->getCurrentSettings()->isNaNHandlingEnabled(); - - NodeList nodes = getNodes(); - for (NodeList::iterator it = nodes.begin(); it != nodes.end(); ++it) { - assert(*it); - - Natron::EffectInstance* liveInstance = (*it)->getLiveInstance(); - assert(liveInstance); - bool duringPaintStrokeCreation = activeRotoPaintNode && (*it)->isDuringPaintStrokeCreation(); - Natron::RenderSafetyEnum safety = (*it)->getCurrentRenderThreadSafety(); - - NodeList rotoPaintNodes; - boost::shared_ptr roto = (*it)->getRotoContext(); - if (roto) { - roto->getRotoPaintTreeNodes(&rotoPaintNodes); - } - - { - U64 nodeHash = 0; - bool hashSet = false; - boost::shared_ptr nodeRequest; - if (request) { - FrameRequestMap::const_iterator foundRequest = request->find(*it); - if (foundRequest != request->end()) { - nodeRequest = foundRequest->second; - nodeHash = nodeRequest->nodeHash; - hashSet = true; - } - } - if (!hashSet) { - nodeHash = (*it)->getHashValue(); - } - - liveInstance->setParallelRenderArgsTLS(time, view, isRenderUserInteraction, isSequential, canAbort, nodeHash, - renderAge,treeRoot, nodeRequest,textureIndex, timeline, isAnalysis,duringPaintStrokeCreation, rotoPaintNodes, safety, doNanHandling, draftMode, viewerProgressReportEnabled, stats); - } - for (NodeList::iterator it2 = rotoPaintNodes.begin(); it2 != rotoPaintNodes.end(); ++it2) { - - boost::shared_ptr childRequest; - U64 nodeHash = 0; - bool hashSet = false; - if (request) { - FrameRequestMap::const_iterator foundRequest = request->find(*it2); - if (foundRequest != request->end()) { - childRequest = foundRequest->second; - nodeHash = childRequest->nodeHash; - hashSet = true; - } - } - if (!hashSet) { - nodeHash = (*it2)->getHashValue(); - } - - (*it2)->getLiveInstance()->setParallelRenderArgsTLS(time, view, isRenderUserInteraction, isSequential, canAbort, nodeHash, renderAge, treeRoot, childRequest, textureIndex, timeline, isAnalysis, activeRotoPaintNode && (*it2)->isDuringPaintStrokeCreation(), NodeList(), (*it2)->getCurrentRenderThreadSafety(), doNanHandling, draftMode, viewerProgressReportEnabled,stats); - } - - if ((*it)->isMultiInstance()) { - - ///If the node has children, set the thread-local storage on them too, even if they do not render, it can be useful for expressions - ///on parameters. - NodeList children; - (*it)->getChildrenMultiInstance(&children); - for (NodeList::iterator it2 = children.begin(); it2!=children.end(); ++it2) { - - boost::shared_ptr childRequest; - U64 nodeHash = 0; - bool hashSet = false; - if (request) { - FrameRequestMap::const_iterator foundRequest = request->find(*it2); - if (foundRequest != request->end()) { - childRequest = foundRequest->second; - nodeHash = childRequest->nodeHash; - hashSet = true; - } - } - if (!hashSet) { - nodeHash = (*it2)->getHashValue(); - } - - assert(*it2); - Natron::EffectInstance* childLiveInstance = (*it2)->getLiveInstance(); - assert(childLiveInstance); - Natron::RenderSafetyEnum childSafety = (*it2)->getCurrentRenderThreadSafety(); - childLiveInstance->setParallelRenderArgsTLS(time, view, isRenderUserInteraction, isSequential, canAbort, nodeHash, renderAge,treeRoot, childRequest, textureIndex, timeline, isAnalysis, false, std::list >(), childSafety, doNanHandling, draftMode, viewerProgressReportEnabled,stats); - - } - } - - - NodeGroup* isGrp = dynamic_cast((*it)->getLiveInstance()); - if (isGrp) { - isGrp->setParallelRenderArgs(time, view, isRenderUserInteraction, isSequential, canAbort, renderAge, treeRoot, request, textureIndex, timeline, activeRotoPaintNode, isAnalysis, draftMode, viewerProgressReportEnabled,stats); - } - - } -} - - -void -NodeCollection::invalidateParallelRenderArgs() -{ - - NodeList nodes = getNodes(); - for (NodeList::iterator it = nodes.begin(); it != nodes.end(); ++it) { - if (!(*it) || !(*it)->getLiveInstance()) { - continue; - } - (*it)->getLiveInstance()->invalidateParallelRenderArgsTLS(); - - if ((*it)->isMultiInstance()) { - - ///If the node has children, set the thread-local storage on them too, even if they do not render, it can be useful for expressions - ///on parameters. - NodeList children; - (*it)->getChildrenMultiInstance(&children); - for (NodeList::iterator it2 = children.begin(); it2!=children.end(); ++it2) { - (*it2)->getLiveInstance()->invalidateParallelRenderArgsTLS(); - - } - } - - NodeList rotoPaintNodes; - boost::shared_ptr roto = (*it)->getRotoContext(); - if (roto) { - roto->getRotoPaintTreeNodes(&rotoPaintNodes); - } - for (NodeList::iterator it2 = rotoPaintNodes.begin(); it2 != rotoPaintNodes.end(); ++it2) { - (*it2)->getLiveInstance()->invalidateParallelRenderArgsTLS(); - } - - NodeGroup* isGrp = dynamic_cast((*it)->getLiveInstance()); - if (isGrp) { - isGrp->invalidateParallelRenderArgs(); - } - } - -} - - void NodeCollection::getParallelRenderArgs(std::map,ParallelRenderArgs >& argsMap) const { @@ -1149,51 +1010,6 @@ NodeCollection::getParallelRenderArgs(std::map,P } -ParallelRenderArgsSetter::ParallelRenderArgsSetter(NodeCollection* n, - double time, - int view, - bool isRenderUserInteraction, - bool isSequential, - bool canAbort, - U64 renderAge, - const boost::shared_ptr& treeRoot, - const FrameRequestMap* request, - int textureIndex, - const TimeLine* timeline, - const boost::shared_ptr& activeRotoPaintNode, - bool isAnalysis, - bool draftMode, - bool viewerProgressReportEnabled, - const boost::shared_ptr& stats) -: collection(n) -, argsMap() -{ - collection->setParallelRenderArgs(time,view,isRenderUserInteraction,isSequential,canAbort,renderAge, treeRoot, request ,textureIndex,timeline, activeRotoPaintNode, isAnalysis, draftMode, viewerProgressReportEnabled,stats); -} - -ParallelRenderArgsSetter::ParallelRenderArgsSetter(const std::map,ParallelRenderArgs >& args) -: collection(0) -, argsMap(args) -{ - for (std::map,ParallelRenderArgs >::iterator it = argsMap.begin(); it != argsMap.end(); ++it) { - it->first->getLiveInstance()->setParallelRenderArgsTLS(it->second); - } -} - -ParallelRenderArgsSetter::~ParallelRenderArgsSetter() -{ - if (collection) { - collection->invalidateParallelRenderArgs(); - } else { - for (std::map,ParallelRenderArgs >::iterator it = argsMap.begin(); it != argsMap.end(); ++it) { - it->first->getLiveInstance()->invalidateParallelRenderArgsTLS(); - } - } -} - - - - struct NodeGroupPrivate { mutable QMutex nodesLock; // protects inputs & outputs @@ -1632,7 +1448,7 @@ static QString escapeString(const QString& str) ret.append('\\'); } else if (str[i] == '"') { ret.append('\\'); - ret.append('"'); + ret.append('\"'); } else if (str[i] == '\'') { ret.append('\\'); ret.append('\''); @@ -1655,6 +1471,7 @@ static QString escapeString(const QString& str) } ret.prepend('"'); ret.append('"'); + return ret; } @@ -1817,7 +1634,8 @@ static bool exportKnobValues(int indentLevel, } // for (int i = 0; i < (*it2)->getDimension(); ++i) - if (knob->getIsSecret()) { + bool isSecretByDefault = knob->getDefaultIsSecret(); + if (knob->isUserKnob() && isSecretByDefault) { if (!hasExportedValue) { hasExportedValue = true; if (mustDefineParam) { @@ -1825,12 +1643,14 @@ static bool exportKnobValues(int indentLevel, WRITE_INDENT(indentLevel); WRITE_STRING("if param is not None:"); } } + + WRITE_INDENT(innerIdent); WRITE_STRING("param.setVisibleByDefault(False)"); - WRITE_INDENT(innerIdent); WRITE_STRING("param.setVisible(False)"); } - for (int i = 0; i < knob->getDimension(); ++i) { - if (!knob->isEnabled(i)) { + if (knob->isUserKnob()) { + bool isSecret = knob->getIsSecret(); + if (isSecret != isSecretByDefault) { if (!hasExportedValue) { hasExportedValue = true; if (mustDefineParam) { @@ -1838,10 +1658,55 @@ static bool exportKnobValues(int indentLevel, WRITE_INDENT(indentLevel); WRITE_STRING("if param is not None:"); } } - - WRITE_INDENT(innerIdent); WRITE_STRING("param.setEnabled(False, " + NUM(i) + ")"); + + QString str("param.setVisible("); + if (isSecret) { + str += "False"; + } else { + str += "True"; + } + str += ")"; + WRITE_INDENT(innerIdent); WRITE_STRING(str); } - } + + bool enabledByDefault = knob->isDefaultEnabled(0); + if (!enabledByDefault) { + if (!hasExportedValue) { + hasExportedValue = true; + if (mustDefineParam) { + WRITE_INDENT(indentLevel); WRITE_STRING("param = " + paramFullName); + WRITE_INDENT(indentLevel); WRITE_STRING("if param is not None:"); + } + } + + WRITE_INDENT(innerIdent); WRITE_STRING("param.setEnabledByDefault(False)"); + } + + for (int i = 0; i < knob->getDimension(); ++i) { + + bool isEnabled = knob->isEnabled(i); + if (isEnabled != enabledByDefault) { + if (!hasExportedValue) { + hasExportedValue = true; + if (mustDefineParam) { + WRITE_INDENT(indentLevel); WRITE_STRING("param = " + paramFullName); + WRITE_INDENT(indentLevel); WRITE_STRING("if param is not None:"); + } + } + + QString str("param.setEnabled("); + if (isEnabled) { + str += "True"; + } else { + str += "False"; + } + str += ", "; + str += NUM(i); + str += ")"; + WRITE_INDENT(innerIdent); WRITE_STRING(str); + } + } + } // isuserknob if (mustDefineParam && hasExportedValue) { WRITE_INDENT(innerIdent); WRITE_STRING("del param"); @@ -1865,6 +1730,16 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, KnobButton* isButton = dynamic_cast(knob.get()); KnobParametric* isParametric = dynamic_cast(knob.get()); + + boost::shared_ptr aliasedParam; + { + std::list > listeners; + knob->getListeners(listeners); + if (!listeners.empty() && listeners.front()->getAliasMaster() == knob) { + aliasedParam = listeners.front(); + } + } + if (isInt) { QString createToken; switch (isInt->getDimension()) { @@ -1885,7 +1760,10 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, WRITE_INDENT(indentLevel); WRITE_STRING("param = " + fullyQualifiedNodeName + createToken + ESC(isInt->getName()) + ", " + ESC(isInt->getLabel()) + ")"); + std::vector defaultValues = isInt->getDefaultValues_mt_safe(); + + assert((int)defaultValues.size() == isInt->getDimension()); for (int i = 0; i < isInt->getDimension() ; ++i) { int min = isInt->getMinimum(i); @@ -1893,24 +1771,26 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, int dMin = isInt->getDisplayMinimum(i); int dMax = isInt->getDisplayMaximum(i); if (min != INT_MIN) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setMinimum(" + NUM(min) + ", " + + WRITE_INDENT(indentLevel); WRITE_STRING("param.setMinimum(" + NUM(min) + ", " + NUM(i) + ")"); } if (max != INT_MAX) { WRITE_INDENT(indentLevel); WRITE_STRING("param.setMaximum(" + NUM(max) + ", " + NUM(i) + ")"); + } if (dMin != INT_MIN) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMinimum(" + NUM(dMin) + ", " + + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMinimum(" + NUM(dMin) + ", " + NUM(i) + ")"); + } if (dMax != INT_MAX) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMaximum(" + NUM(dMax) + ", " + + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMaximum(" + NUM(dMax) + ", " + NUM(i) + ")"); + } - if (defaultValues[i] != 0) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + NUM(defaultValues[i]) + ", " + NUM(i) + ")"); - } + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + NUM(defaultValues[i]) + ", " + NUM(i) + ")"); + } } else if (isDouble) { QString createToken; @@ -1932,6 +1812,8 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, WRITE_INDENT(indentLevel); WRITE_STRING("param = " + fullyQualifiedNodeName + createToken + ESC(isDouble->getName()) + ", " + ESC(isDouble->getLabel()) + ")"); + + std::vector defaultValues = isDouble->getDefaultValues_mt_safe(); assert((int)defaultValues.size() == isDouble->getDimension()); for (int i = 0; i < isDouble->getDimension() ; ++i) { @@ -1940,23 +1822,28 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, double dMin = isDouble->getDisplayMinimum(i); double dMax = isDouble->getDisplayMaximum(i); if (min != -DBL_MAX) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setMinimum(" + NUM(min) + ", " + + WRITE_INDENT(indentLevel); WRITE_STRING("param.setMinimum(" + NUM(min) + ", " + NUM(i) + ")"); + } if (max != DBL_MAX) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setMaximum(" + NUM(max) + ", " + + WRITE_INDENT(indentLevel); WRITE_STRING("param.setMaximum(" + NUM(max) + ", " + NUM(i) + ")"); + } if (dMin != -DBL_MAX) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMinimum(" + NUM(dMin) + ", " + + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMinimum(" + NUM(dMin) + ", " + NUM(i) + ")"); + } if (dMax != DBL_MAX) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMaximum(" + NUM(dMax) + ", " + + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMaximum(" + NUM(dMax) + ", " + NUM(i) + ")"); + } if (defaultValues[i] != 0.) { WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + NUM(defaultValues[i]) + ", " + NUM(i) + ")"); + } } @@ -1965,11 +1852,13 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, WRITE_INDENT(indentLevel); WRITE_STRING("param = " + fullyQualifiedNodeName + ".createBooleanParam(" + ESC(isBool->getName()) + ", " + ESC(isBool->getLabel()) + ")"); + std::vector defaultValues = isBool->getDefaultValues_mt_safe(); assert((int)defaultValues.size() == isBool->getDimension()); if (defaultValues[0]) { WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + NUM(defaultValues[0]) + ")"); + } @@ -1977,34 +1866,51 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, WRITE_INDENT(indentLevel); WRITE_STRING("param = " + fullyQualifiedNodeName + ".createChoiceParam(" + ESC(isChoice->getName()) + ", " + ESC(isChoice->getLabel()) + ")"); - std::vector entries = isChoice->getEntries_mt_safe(); - std::vector helps = isChoice->getEntriesHelp_mt_safe(); - if (entries.size() > 0) { - if (helps.empty()) { - for (U32 i = 0; i < entries.size(); ++i) { - helps.push_back(""); + + KnobChoice* aliasedIsChoice = dynamic_cast(aliasedParam.get()); + + if (!aliasedIsChoice) { + std::vector entries = isChoice->getEntries_mt_safe(); + std::vector helps = isChoice->getEntriesHelp_mt_safe(); + if (entries.size() > 0) { + if (helps.empty()) { + for (U32 i = 0; i < entries.size(); ++i) { + helps.push_back(""); + } + } + WRITE_INDENT(indentLevel); ts << "entries = [ (" << ESC(entries[0]) << ", " << ESC(helps[0]) << "),\n"; + for (U32 i = 1; i < entries.size(); ++i) { + QString endToken = (i == entries.size() - 1) ? ")]" : "),"; + WRITE_INDENT(indentLevel); WRITE_STRING("(" + ESC(entries[i]) + ", " + ESC(helps[i]) + endToken); } + WRITE_INDENT(indentLevel); WRITE_STATIC_LINE("param.setOptions(entries)"); + WRITE_INDENT(indentLevel); WRITE_STATIC_LINE("del entries"); + } + std::vector defaultValues = isChoice->getDefaultValues_mt_safe(); + assert((int)defaultValues.size() == isChoice->getDimension()); + if (defaultValues[0] != 0) { + std::string entryStr = isChoice->getEntry(defaultValues[0]); + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + ESC(entryStr) + ")"); + } - WRITE_INDENT(indentLevel); ts << "entries = [ (" << ESC(entries[0]) << ", " << ESC(helps[0]) << "),\n"; - for (U32 i = 1; i < entries.size(); ++i) { - QString endToken = (i == entries.size() - 1) ? ")]" : "),"; - WRITE_INDENT(indentLevel); WRITE_STRING("(" + ESC(entries[i]) + ", " + ESC(helps[i]) + endToken); + } else { + std::vector defaultValues = isChoice->getDefaultValues_mt_safe(); + assert((int)defaultValues.size() == isChoice->getDimension()); + if (defaultValues[0] != 0) { + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + NUM(defaultValues[0]) + ")"); + } - WRITE_INDENT(indentLevel); WRITE_STATIC_LINE("param.setOptions(entries)"); - WRITE_INDENT(indentLevel); WRITE_STATIC_LINE("del entries"); } - std::vector defaultValues = isChoice->getDefaultValues_mt_safe(); - assert((int)defaultValues.size() == isChoice->getDimension()); - if (defaultValues[0] != 0) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + NUM(defaultValues[0]) + ")"); - } + + } else if (isColor) { QString hasAlphaStr = (isColor->getDimension() == 4) ? "True" : "False"; WRITE_INDENT(indentLevel); WRITE_STRING("param = " + fullyQualifiedNodeName + ".createColorParam(" + ESC(isColor->getName()) + ", " + ESC(isColor->getLabel()) + ", " + hasAlphaStr + ")"); + std::vector defaultValues = isColor->getDefaultValues_mt_safe(); assert((int)defaultValues.size() == isColor->getDimension()); @@ -2014,23 +1920,28 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, double dMin = isColor->getDisplayMinimum(i); double dMax = isColor->getDisplayMaximum(i); if (min != -DBL_MAX) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setMinimum(" + NUM(min) + ", " + + WRITE_INDENT(indentLevel); WRITE_STRING("param.setMinimum(" + NUM(min) + ", " + NUM(i) + ")"); + } if (max != DBL_MAX) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setMaximum(" + NUM(max) + ", " + + WRITE_INDENT(indentLevel); WRITE_STRING("param.setMaximum(" + NUM(max) + ", " + NUM(i) + ")"); + } if (dMin != -DBL_MAX) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMinimum(" + NUM(dMin) + ", " + + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMinimum(" + NUM(dMin) + ", " + NUM(i) + ")"); } + if (dMax != DBL_MAX) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMaximum(" + NUM(dMax) + ", " + + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDisplayMaximum(" + NUM(dMax) + ", " + NUM(i) + ")"); + } if (defaultValues[i] != 0.) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + NUM(defaultValues[i]) + ", " + NUM(i) + ")"); + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + NUM(defaultValues[i]) + ", " + NUM(i) + ")"); + } } @@ -2058,11 +1969,13 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, } WRITE_INDENT(indentLevel); WRITE_STRING("param.setType(NatronEngine.StringParam.TypeEnum." + typeStr + ")"); + std::vector defaultValues = isStr->getDefaultValues_mt_safe(); assert((int)defaultValues.size() == isStr->getDimension()); QString def(defaultValues[0].c_str()); if (!def.isEmpty()) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + ESC(def) + ")"); + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + ESC(def) + ")"); + } } else if (isFile) { @@ -2071,11 +1984,13 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, QString seqStr = isFile->isInputImageFile() ? "True" : "False"; WRITE_INDENT(indentLevel); WRITE_STRING("param.setSequenceEnabled("+ seqStr + ")"); + std::vector defaultValues = isFile->getDefaultValues_mt_safe(); assert((int)defaultValues.size() == isFile->getDimension()); QString def(defaultValues[0].c_str()); if (!def.isEmpty()) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + def + ")"); + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + def + ")"); + } } else if (isOutFile) { @@ -2086,11 +2001,13 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, QString seqStr = isOutFile->isOutputImageFile() ? "True" : "False"; WRITE_INDENT(indentLevel); WRITE_STRING("param.setSequenceEnabled("+ seqStr + ")"); + std::vector defaultValues = isOutFile->getDefaultValues_mt_safe(); assert((int)defaultValues.size() == isOutFile->getDimension()); QString def(defaultValues[0].c_str()); if (!def.isEmpty()) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + ESC(def) + ")"); + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + ESC(def) + ")"); + } } else if (isPath) { @@ -2101,12 +2018,14 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, WRITE_INDENT(indentLevel); WRITE_STRING("param.setAsMultiPathTable()"); } + std::vector defaultValues = isPath->getDefaultValues_mt_safe(); assert((int)defaultValues.size() == isPath->getDimension()); QString def(defaultValues[0].c_str()); if (!def.isEmpty()) { - WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + ESC(def) + ")"); + WRITE_INDENT(indentLevel); WRITE_STRING("param.setDefaultValue(" + ESC(def) + ")"); } + } else if (isGrp) { WRITE_INDENT(indentLevel); WRITE_STRING("param = " + fullyQualifiedNodeName + ".createGroupParam(" + @@ -2140,7 +2059,9 @@ static void exportUserKnob(int indentLevel,const boost::shared_ptr& knob, WRITE_INDENT(indentLevel); WRITE_STATIC_LINE("#Set param properties"); QString help(knob->getHintToolTip().c_str()); - WRITE_INDENT(indentLevel); WRITE_STRING("param.setHelp(" + ESC(help) + ")"); + if (!aliasedParam || aliasedParam->getHintToolTip() != knob->getHintToolTip()) { + WRITE_INDENT(indentLevel); WRITE_STRING("param.setHelp(" + ESC(help) + ")"); + } if (knob->isNewLineActivated()) { WRITE_INDENT(indentLevel); WRITE_STRING("param.setAddNewLine(True)"); } else { @@ -2325,7 +2246,14 @@ static void exportAllNodeKnobs(int indentLevel,const boost::shared_ptr userPages; for (std::vector >::const_iterator it2 = knobs.begin(); it2 != knobs.end(); ++it2) { if ((*it2)->getIsPersistant() && !(*it2)->isUserKnob()) { - if (exportKnobValues(indentLevel,*it2,"lastNode.getParam(\"" + QString((*it2)->getName().c_str()) + "\")", true, ts)) { + QString getParamStr("lastNode.getParam(\""); + const std::string& paramName = (*it2)->getName(); + if (paramName.empty()) { + continue; + } + getParamStr += paramName.c_str(); + getParamStr += "\")"; + if (exportKnobValues(indentLevel,*it2,getParamStr, true, ts)) { WRITE_STATIC_LINE(""); } @@ -2354,6 +2282,23 @@ static void exportAllNodeKnobs(int indentLevel,const boost::shared_ptr pagesOrdering = node->getPagesOrder(); + if (!pagesOrdering.empty()) { + QString line("lastNode.setPagesOrder(["); + std::list::iterator next = pagesOrdering.begin(); + ++next; + for (std::list::iterator it = pagesOrdering.begin(); it!=pagesOrdering.end(); ++it) { + line += '\''; + line += it->c_str(); + line += '\''; + if (next != pagesOrdering.end()) { + line += ", "; + ++next; + } + } + line += "])"; + WRITE_INDENT(indentLevel); WRITE_STRING(line); + } WRITE_INDENT(indentLevel); WRITE_STATIC_LINE("lastNode.refreshUserParamsGUI()"); } @@ -2383,29 +2328,55 @@ static void exportAllNodeKnobs(int indentLevel,const boost::shared_ptr& groupNode, const boost::shared_ptr& node, - const QString& nodeName, - QTextStream& ts) + const QString& groupName, + const QString& nodeName, + QTextStream& ts) { bool hasExportedLink = false; const std::vector >& knobs = node->getKnobs(); for (std::vector >::const_iterator it2 = knobs.begin(); it2 != knobs.end(); ++it2) { QString paramName = nodeName + ".getParam(\"" + QString((*it2)->getName().c_str()) + "\")"; - bool hasDefined = false; - for (int i = 0; i < (*it2)->getDimension(); ++i) { - std::string expr = (*it2)->getExpression(i); - QString hasRetVar = (*it2)->isExpressionUsingRetVariable(i) ? "True" : "False"; - if (!expr.empty()) { - if (!hasDefined) { - WRITE_INDENT(indentLevel); WRITE_STRING("param = " + paramName); - hasDefined = true; - } - hasExportedLink = true; - WRITE_INDENT(indentLevel); WRITE_STRING("param.setExpression(" + ESC(expr) + ", " + - hasRetVar + ", " + NUM(i) + ")"); + + //Check for alias link + boost::shared_ptr alias = (*it2)->getAliasMaster(); + if (alias) { + if (!hasDefined) { + WRITE_INDENT(indentLevel); WRITE_STRING("param = " + paramName); + hasDefined = true; } + hasExportedLink = true; + Natron::EffectInstance* aliasHolder = dynamic_cast(alias->getHolder()); + assert(aliasHolder); + QString aliasName; + if (aliasHolder == groupNode->getLiveInstance()) { + aliasName = groupName; + } else { + aliasName = groupName + aliasHolder->getNode()->getScriptName_mt_safe().c_str(); + } + aliasName += '.'; + aliasName += alias->getName().c_str(); + + WRITE_INDENT(indentLevel); WRITE_STRING(aliasName + ".setAsAlias(" + paramName + ")"); + } else { + + for (int i = 0; i < (*it2)->getDimension(); ++i) { + std::string expr = (*it2)->getExpression(i); + QString hasRetVar = (*it2)->isExpressionUsingRetVariable(i) ? "True" : "False"; + if (!expr.empty()) { + if (!hasDefined) { + WRITE_INDENT(indentLevel); WRITE_STRING("param = " + paramName); + hasDefined = true; + } + hasExportedLink = true; + WRITE_INDENT(indentLevel); WRITE_STRING("param.setExpression(" + ESC(expr) + ", " + + hasRetVar + ", " + NUM(i) + ")"); + } + + } } if (hasDefined) { WRITE_INDENT(indentLevel); WRITE_STATIC_LINE("del param"); @@ -2526,6 +2497,10 @@ static void exportGroupInternal(int indentLevel,const NodeCollection* collection WRITE_STATIC_LINE(""); const NodeGroup* isGroup = dynamic_cast(collection); + NodePtr groupNode; + if (isGroup) { + groupNode = isGroup->getNode(); + } if (isGroup) { WRITE_INDENT(indentLevel); WRITE_STATIC_LINE("#Create the parameters of the group node the same way we did for all internal nodes"); WRITE_INDENT(indentLevel); WRITE_STRING("lastNode = " + groupName); @@ -2561,10 +2536,13 @@ static void exportGroupInternal(int indentLevel,const NodeCollection* collection for (NodeList::iterator it = exportedNodes.begin(); it != exportedNodes.end(); ++it) { QString nodeQualifiedName(groupName + (*it)->getScriptName_mt_safe().c_str()); - if (exportKnobLinks(indentLevel,*it,nodeQualifiedName, ts)) { + if (exportKnobLinks(indentLevel,groupNode, *it, groupName, nodeQualifiedName, ts)) { hasExported = true; } } + if (isGroup) { + exportKnobLinks(indentLevel, groupNode, groupNode, groupName, groupName, ts); + } if (hasExported) { WRITE_STATIC_LINE(""); } @@ -2611,7 +2589,7 @@ NodeCollection::exportGroupToPython(const QString& pluginID, WRITE_STATIC_LINE(""); WRITE_STATIC_LINE("def getLabel():"); - WRITE_INDENT(1);WRITE_STRING("return \"" + pluginLabel + "\""); + WRITE_INDENT(1);WRITE_STRING("return " + ESC(pluginLabel)); WRITE_STATIC_LINE(""); WRITE_STATIC_LINE("def getVersion():"); @@ -2620,7 +2598,7 @@ NodeCollection::exportGroupToPython(const QString& pluginID, if (!pluginIconPath.isEmpty()) { WRITE_STATIC_LINE("def getIconPath():"); - WRITE_INDENT(1);WRITE_STRING("return \"" + pluginIconPath + "\""); + WRITE_INDENT(1);WRITE_STRING("return " + ESC(pluginIconPath)); WRITE_STATIC_LINE(""); } @@ -2630,7 +2608,7 @@ NodeCollection::exportGroupToPython(const QString& pluginID, if (!pluginDescription.isEmpty()) { WRITE_STATIC_LINE("def getPluginDescription():"); - WRITE_INDENT(1);WRITE_STRING("return \"" + pluginDescription + "\""); + WRITE_INDENT(1);WRITE_STRING("return " + ESC(pluginDescription)); WRITE_STATIC_LINE(""); } diff --git a/Engine/NodeGroup.h b/Engine/NodeGroup.h index cbb8a95a2e..58497e1564 100644 --- a/Engine/NodeGroup.h +++ b/Engine/NodeGroup.h @@ -99,7 +99,13 @@ class NodeCollection **/ void initNodeName(const std::string& pluginLabel,std::string* nodeName); - bool setNodeName(const std::string& baseName,bool appendDigit,bool errorIfExists,std::string* nodeName); + /** + * @brief Given the baseName, set in nodeName a possible script-name for the node. + * @param appendDigit If a node with the same script-name exists, try to add digits at the end until no match is found + * @param errorIfExists If a node with the same script-name exists, error + * This function throws a runtime exception with the error message in case of error. + **/ + void setNodeName(const std::string& baseName,bool appendDigit,bool errorIfExists,std::string* nodeName); /** * @brief Returns true if there is one or more nodes in the collection. @@ -237,27 +243,7 @@ class NodeCollection * @brief Computes the union of the frame range of all readers in the group and subgroups. **/ void recomputeFrameRangeForAllReaders(int* firstFrame,int* lastFrame); - - /** - * @brief Recursively sets render preferences for the rendering of a frame for the current thread. - * This is thread local storage - **/ - void setParallelRenderArgs(double time, - int view, - bool isRenderUserInteraction, - bool isSequential, - bool canAbort, - U64 renderAge, - const boost::shared_ptr& treeRoot, - const FrameRequestMap* request, - int textureIndex, - const TimeLine* timeline, - const boost::shared_ptr& activeRotoPaintNode, - bool isAnalysis, - bool draftMode, - bool viewerProgressReportEnabled, - const boost::shared_ptr& stats); - void invalidateParallelRenderArgs(); + void getParallelRenderArgs(std::map,ParallelRenderArgs >& argsMap) const; @@ -303,46 +289,7 @@ class NodeCollection boost::scoped_ptr _imp; }; -struct ParallelRenderArgs; -class ParallelRenderArgsSetter -{ - NodeCollection* collection; - std::map,ParallelRenderArgs > argsMap; - - -public: - - /** - * @brief Set the TLS for rendering a frame on the NodeCollection n and all its children recursively. - * The argument passed here should always be the project, that is all nodes in the project should have their - * TLS set regardless whether they are connected to the tree that takes root from the treeRoot parameter. - * We do this because TLS is needed to know the correct frame, view at which the frame is evaluated (i.e rendered) - * even in nodes that do not belong in the tree. The reason why is because the nodes in the tree may have parameters - * relying on other nodes that do not belong in the tree through expressions. - * An enhancement could be to set the TLS only on the nodes in the tree and on the nodes that are dependencies through - * expressions. - **/ - ParallelRenderArgsSetter(NodeCollection* n, - double time, - int view, - bool isRenderUserInteraction, - bool isSequential, - bool canAbort, - U64 renderAge, - const boost::shared_ptr& treeRoot, - const FrameRequestMap* request, - int textureIndex, - const TimeLine* timeline, - const boost::shared_ptr& activeRotoPaintNode, - bool isAnalysis, - bool draftMode, - bool viewerProgressReportEnabled, - const boost::shared_ptr& stats); - - ParallelRenderArgsSetter(const std::map,ParallelRenderArgs >& args); - - virtual ~ParallelRenderArgsSetter(); -}; + struct NodeGroupPrivate; diff --git a/Engine/NodeGroupSerialization.cpp b/Engine/NodeGroupSerialization.cpp index af133fb9c7..fa0dd96fd6 100644 --- a/Engine/NodeGroupSerialization.cpp +++ b/Engine/NodeGroupSerialization.cpp @@ -34,6 +34,8 @@ #include "Engine/ViewerInstance.h" #include +using namespace Natron; + void NodeCollectionSerialization::initialize(const NodeCollection& group) { @@ -124,7 +126,11 @@ NodeCollectionSerialization::restoreFromSerialization(const std::list< boost::sh QString(), CreateNodeArgs::DefaultValuesList(), group)); - parent->setScriptName( (*it)->getMultiInstanceParentName().c_str() ); + try { + parent->setScriptName( (*it)->getMultiInstanceParentName().c_str() ); + } catch (...) { + + } parentsToReconnect.insert( std::make_pair(parent, it) ); } } diff --git a/Engine/NodeSerialization.cpp b/Engine/NodeSerialization.cpp index b1dcd57a38..f5b561a141 100644 --- a/Engine/NodeSerialization.cpp +++ b/Engine/NodeSerialization.cpp @@ -67,9 +67,11 @@ NodeSerialization::NodeSerialization(const boost::shared_ptr & n,b KnobButton* isButton = dynamic_cast( knobs[i].get() ); //KnobChoice* isChoice = dynamic_cast( knobs[i].get() ); - if (isPage && knobs[i]->isUserKnob()) { - userPages.push_back(knobs[i]); - continue; + if (isPage) { + _pagesIndexes.push_back(knobs[i]->getName()); + if (knobs[i]->isUserKnob()) { + userPages.push_back(knobs[i]); + } } if (!knobs[i]->isUserKnob() && diff --git a/Engine/NodeSerialization.h b/Engine/NodeSerialization.h index a7423d5329..08d6ab0cbb 100644 --- a/Engine/NodeSerialization.h +++ b/Engine/NodeSerialization.h @@ -62,7 +62,8 @@ GCC_DIAG_ON(unused-parameter) #define NODE_SERIALIZATION_INTRODUCES_PYTHON_MODULE_VERSION 11 #define NODE_SERIALIZATION_INTRODUCES_CACHE_ID 12 #define NODE_SERIALIZATION_SERIALIZE_PYTHON_MODULE_ALWAYS 13 -#define NODE_SERIALIZATION_CURRENT_VERSION NODE_SERIALIZATION_SERIALIZE_PYTHON_MODULE_ALWAYS +#define NODE_SERIALIZATION_SERIALIZE_PAGE_INDEX 14 +#define NODE_SERIALIZATION_CURRENT_VERSION NODE_SERIALIZATION_SERIALIZE_PAGE_INDEX @@ -205,6 +206,11 @@ class NodeSerialization { return _multiInstanceParentName; } + + const std::list& getPagesOrdered() const + { + return _pagesIndexes; + } const std::list >& getUserPages() const { @@ -239,6 +245,7 @@ class NodeSerialization boost::shared_ptr _node; std::string _multiInstanceParentName; std::list > _userPages; + std::list _pagesIndexes; ///If this node is a group or a multi-instance, this is the children std::list< boost::shared_ptr > _children; @@ -282,6 +289,12 @@ class NodeSerialization ar & boost::serialization::make_nvp("item",**it); } + int pageSizes = (int)_pagesIndexes.size(); + ar & boost::serialization::make_nvp("PagesCount",pageSizes); + for (std::list::const_iterator it = _pagesIndexes.begin(); it!= _pagesIndexes.end(); ++it) { + ar & boost::serialization::make_nvp("name",*it); + } + int nodesCount = (int)_children.size(); ar & boost::serialization::make_nvp("Children",nodesCount); @@ -373,6 +386,17 @@ class NodeSerialization ar & boost::serialization::make_nvp("item",*s); _userPages.push_back(s); } + if (version >= NODE_SERIALIZATION_SERIALIZE_PAGE_INDEX) { + int count; + ar & boost::serialization::make_nvp("PagesCount",count); + for (int i = 0; i < count; ++i) { + std::string name; + ar & boost::serialization::make_nvp("name",name); + _pagesIndexes.push_back(name); + } + } else { + _pagesIndexes.push_back(NATRON_USER_MANAGED_KNOBS_PAGE); + } } if (version >= NODE_SERIALIZATION_INTRODUCES_GROUPS) { diff --git a/Engine/NodeWrapper.cpp b/Engine/NodeWrapper.cpp index 9020825b77..649e6fc107 100644 --- a/Engine/NodeWrapper.cpp +++ b/Engine/NodeWrapper.cpp @@ -253,7 +253,12 @@ Effect::getScriptName() const bool Effect::setScriptName(const std::string& scriptName) { - return _node->setScriptName(scriptName); + try { + _node->setScriptName(scriptName); + } catch (...) { + return false; + } + return true; } std::string @@ -658,7 +663,7 @@ Effect::getUserPageParam() const void UserParamHolder::refreshUserParamsGUI() { - _holder->refreshKnobs(); + _holder->refreshKnobs(false); } Effect* @@ -760,3 +765,12 @@ Effect::getAvailableLayers() const } return ret; } + +void +Effect::setPagesOrder(const std::list& pages) +{ + if (!_node) { + return; + } + _node->setPagesOrder(pages); +} diff --git a/Engine/NodeWrapper.h b/Engine/NodeWrapper.h index b144ae0a0a..08fd63f605 100644 --- a/Engine/NodeWrapper.h +++ b/Engine/NodeWrapper.h @@ -356,6 +356,8 @@ class Effect : public Group, public UserParamHolder bool addUserPlane(const std::string& planeName, const std::vector& channels); std::map getAvailableLayers() const; + + void setPagesOrder(const std::list& pages); }; #endif // NODEWRAPPER_H diff --git a/Engine/OfxClipInstance.cpp b/Engine/OfxClipInstance.cpp index 5f2ffe3f29..5a4a54bc3a 100644 --- a/Engine/OfxClipInstance.cpp +++ b/Engine/OfxClipInstance.cpp @@ -28,7 +28,8 @@ #include #include -#include +#include +#include #include "Global/Macros.h" @@ -860,21 +861,22 @@ OfxClipInstance::getInputImageInternal(OfxTime time, Get mipmaplevel, and transform concatenation data from the TLS */ if (tls) { - if (!tls->isViewValid) { + if (view == -1) { + if (!tls->isViewValid) { #ifdef DEBUG - if (QThread::currentThread() != qApp->thread()) { - qDebug() << _nodeInstance->getNode()->getScriptName_mt_safe().c_str() << " is trying to call clipGetImage on a thread " - "not controlled by Natron (probably from the multi-thread suite).\n If you're a developer of that plug-in, please " - "fix it. Natron is now going to try to recover from that mistake but doing so can yield unpredictable results."; - } + if (QThread::currentThread() != qApp->thread()) { + qDebug() << _nodeInstance->getNode()->getScriptName_mt_safe().c_str() << " is trying to call clipGetImage on a thread " + "not controlled by Natron (probably from the multi-thread suite).\n If you're a developer of that plug-in, please " + "fix it. Natron is now going to try to recover from that mistake but doing so can yield unpredictable results."; + } #endif - view = 0; - } else { - if (view == -1) { + view = 0; + } else { view = tls->view; } + } - + if (!tls->isMipmapLevelValid) { mipMapLevel = 0; } else { diff --git a/Engine/OfxImageEffectInstance.cpp b/Engine/OfxImageEffectInstance.cpp index b042b3883a..d22e66b4b5 100644 --- a/Engine/OfxImageEffectInstance.cpp +++ b/Engine/OfxImageEffectInstance.cpp @@ -832,7 +832,7 @@ OfxImageEffectInstance::timeLineGotoTime(double t) bool redrawNeeded = _ofxEffectInstance->checkIfOverlayRedrawNeeded(); Q_UNUSED(redrawNeeded); - _ofxEffectInstance->getApp()->getTimeLine()->seekFrame( (int)t, false, 0, Natron::eTimelineChangeReasonPlaybackSeek); + _ofxEffectInstance->getApp()->getTimeLine()->seekFrame( (int)t, false, 0, Natron::eTimelineChangeReasonOtherSeek); } /// get the first and last times available on the effect's timeline diff --git a/Engine/OfxImageEffectInstance.h b/Engine/OfxImageEffectInstance.h index 1caacccf0e..401bd5f370 100644 --- a/Engine/OfxImageEffectInstance.h +++ b/Engine/OfxImageEffectInstance.h @@ -41,16 +41,6 @@ CLANG_DIAG_ON(unknown-pragmas) #include "Engine/EngineFwd.h" -namespace OFX { - namespace Host { - class Plugin; - namespace Property - { - class Set; - } - } -} - namespace Natron { class OfxImageEffectInstance diff --git a/Engine/OfxParamInstance.cpp b/Engine/OfxParamInstance.cpp index 8ef16f88ee..7f724b60f1 100644 --- a/Engine/OfxParamInstance.cpp +++ b/Engine/OfxParamInstance.cpp @@ -2846,7 +2846,7 @@ OfxStringInstance::set(OfxTime time, const char* str) { - assert( !KnobString::canAnimateStatic() ); + assert( KnobString::canAnimateStatic() ); if (_fileKnob.lock()) { std::string s(str); projectEnvVar_setProxy(s); diff --git a/Engine/OutputEffectInstance.h b/Engine/OutputEffectInstance.h index 2ece9071d8..06ef3751a0 100644 --- a/Engine/OutputEffectInstance.h +++ b/Engine/OutputEffectInstance.h @@ -31,45 +31,15 @@ #endif #include "Global/Macros.h" -//#include "Global/GlobalDefines.h" -//#include "Global/KeySymbols.h" -// -#include "Engine/EffectInstance.h" -//#include "Engine/ImageComponents.h" -//#include "Engine/ImageLocker.h" -//#include "Engine/Knob.h" // for KnobHolder -//#include "Engine/ParallelRenderArgs.h" -//#include "Engine/RectD.h" -//#include "Engine/RectI.h" -//#include "Engine/RenderStats.h" +#include "Engine/EffectInstance.h" +#include "Engine/EngineFwd.h" class QThread; -class Hash64; -class Format; -class TimeLine; -class OverlaySupport; -class PluginMemory; -class BlockingBackgroundRender; -class NodeSerialization; -class ViewerInstance; -class RenderEngine; -class BufferableObject; -namespace Natron { -class OutputEffectInstance; -} -namespace Transform { -struct Matrix3x3; -} namespace Natron { -class Node; -class ImageKey; -class Image; -class ImageParams; - class OutputEffectInstance : public Natron::EffectInstance diff --git a/Engine/OutputSchedulerThread.cpp b/Engine/OutputSchedulerThread.cpp index c357828167..38b232fb28 100644 --- a/Engine/OutputSchedulerThread.cpp +++ b/Engine/OutputSchedulerThread.cpp @@ -138,8 +138,9 @@ typedef std::list RenderThreads; // Struct used in a queue when rendering the current frame with a viewer, the id is meaningless just to have a member // in the structure. We then compare the pointer of this struct -struct RequestedFrame +class RequestedFrame { +public: int id; }; @@ -1869,8 +1870,9 @@ OutputSchedulerThread::runCallbackWithVariables(const QString& callback) if (!callback.isEmpty()) { QString script = callback; std::string appID = _imp->outputEffect->getApp()->getAppIDString(); - std::string thisNodeStr = appID + "." + _imp->outputEffect->getNode()->getFullyQualifiedName(); - script.append(thisNodeStr.c_str()); + std::string nodeName = _imp->outputEffect->getNode()->getFullyQualifiedName(); + std::string nodeFullName = appID + "." + nodeName; + script.append(nodeFullName.c_str()); script.append(","); script.append(appID.c_str()); script.append(")\n"); @@ -2161,8 +2163,7 @@ class DefaultRenderFrameRunnable : public RenderThreadTask return; } - ParallelRenderArgsSetter frameRenderArgs(activeInputToRender->getApp()->getProject().get(), - time, + ParallelRenderArgsSetter frameRenderArgs(time, viewsToRender[view], false, // is this render due to user interaction ? sequentiallity == Natron::eSequentialPreferenceOnlySequential || sequentiallity == Natron::eSequentialPreferencePreferSequential, // is this sequential ? @@ -2264,8 +2265,7 @@ DefaultScheduler::processFrame(const BufferedFrames& frames) ignore_result(_effect->getRegionOfDefinition_public(hash,it->time, scale, it->view, &rod, &isProjectFormat)); rod.toPixelEnclosing(0, par, &roi); - ParallelRenderArgsSetter frameRenderArgs(_effect->getApp()->getProject().get(), - it->time, + ParallelRenderArgsSetter frameRenderArgs(it->time, it->view, false, // is this render due to user interaction ? canOnlyHandleOneView, // is this sequential ? @@ -3016,7 +3016,7 @@ struct ViewerCurrentFrameRequestSchedulerPrivate }; -static void renderCurrentFrameFunctor(CurrentFrameFunctorArgs& args) +static void renderCurrentFrameFunctor(CurrentFrameFunctorArgs args) { ///The viewer always uses the scheduler thread to regulate the output rate, @see ViewerInstance::renderViewer_internal @@ -3029,7 +3029,7 @@ static void renderCurrentFrameFunctor(CurrentFrameFunctorArgs& args) stat = args.viewer->renderViewer(args.view,QThread::currentThread() == qApp->thread(),false,args.viewerHash,args.canAbort, NodePtr(), true,args.args, args.request, args.stats); } else { - stat = args.viewer->getViewerArgsAndRenderViewer(args.time, args.canAbort, args.view, args.viewerHash, args.isRotoPaintRequest, args.stats,&args.args[0],&args.args[1]); + stat = args.viewer->getViewerArgsAndRenderViewer(args.time, args.canAbort, args.view, args.viewerHash, args.isRotoPaintRequest, args.strokeItem, args.stats,&args.args[0],&args.args[1]); } } catch (...) { stat = eStatusFailed; @@ -3295,12 +3295,21 @@ ViewerCurrentFrameRequestScheduler::renderCurrentFrame(bool enableRenderStats,bo if (enableRenderStats) { stats.reset(new RenderStats(enableRenderStats)); } - NodePtr isUserRotopainting = _imp->viewer->getApp()->getIsUserPainting(); + + boost::shared_ptr rotoPaintNode; + boost::shared_ptr curStroke; + bool isDrawing; + _imp->viewer->getApp()->getActiveRotoDrawingStroke(&rotoPaintNode, &curStroke,&isDrawing); + if (!isDrawing) { + rotoPaintNode.reset(); + curStroke.reset(); + } + boost::shared_ptr args[2]; - if (!isUserRotopainting) { + if (!rotoPaintNode) { for (int i = 0; i < 2; ++i) { args[i].reset(new ViewerArgs); - status[i] = _imp->viewer->getRenderViewerArgsAndCheckCache_public(frame, false, canAbort, view, i, viewerHash,isUserRotopainting, true, stats, args[i].get()); + status[i] = _imp->viewer->getRenderViewerArgsAndCheckCache_public(frame, false, canAbort, view, i, viewerHash,rotoPaintNode, true, stats, args[i].get()); } if (status[0] == eStatusFailed && status[1] == eStatusFailed) { @@ -3340,7 +3349,8 @@ ViewerCurrentFrameRequestScheduler::renderCurrentFrame(bool enableRenderStats,bo functorArgs.viewerHash = viewerHash; functorArgs.scheduler = _imp.get(); functorArgs.canAbort = canAbort; - functorArgs.isRotoPaintRequest = isUserRotopainting; + functorArgs.isRotoPaintRequest = rotoPaintNode; + functorArgs.strokeItem = curStroke; functorArgs.stats = stats; if (appPTR->getCurrentSettings()->getNumberOfThreads() == -1) { @@ -3367,7 +3377,7 @@ ViewerCurrentFrameRequestScheduler::renderCurrentFrame(bool enableRenderStats,bo int maxThreads = QThreadPool::globalInstance()->maxThreadCount(); //When painting, limit the number of threads to 1 to be sure strokes are painted in the right order - if (_imp->viewer->getApp()->getIsUserPainting().get() != 0) { + if (rotoPaintNode) { maxThreads = 1; } if (maxThreads == 1 || (QThreadPool::globalInstance()->activeThreadCount() >= maxThreads - 1)) { diff --git a/Engine/OutputSchedulerThread.h b/Engine/OutputSchedulerThread.h index b313d81110..c55f2f218e 100644 --- a/Engine/OutputSchedulerThread.h +++ b/Engine/OutputSchedulerThread.h @@ -32,22 +32,11 @@ #include #include "Global/GlobalDefines.h" +#include "Engine/EngineFwd.h" -///Natron -class ViewerInstance; -class RenderStats; typedef boost::shared_ptr RenderStatsPtr; -namespace Natron { - class Node; - class EffectInstance; - class OutputEffectInstance; -} - -class RenderStats; -class RenderEngine; - /** * @brief Stub class used by internal implementation of OutputSchedulerThread to pass objects through signal/slots **/ @@ -550,7 +539,7 @@ class ViewerDisplayScheduler : public OutputSchedulerThread * Instead of re-using the OutputSchedulerClass and adding extra handling for special cases we separated it in a different class, specialized for this kind * of "current frame re-rendering" which needs much less code to run than all the code in OutputSchedulerThread **/ -struct RequestedFrame; + struct ViewerCurrentFrameRequestSchedulerPrivate; class ViewerCurrentFrameRequestScheduler : public QThread { @@ -602,6 +591,7 @@ struct CurrentFrameFunctorArgs ViewerCurrentFrameRequestSchedulerPrivate* scheduler; bool canAbort; boost::shared_ptr isRotoPaintRequest; + boost::shared_ptr strokeItem; boost::shared_ptr args[2]; }; diff --git a/Engine/OverlaySupport.h b/Engine/OverlaySupport.h index 8c6b270183..83fa348fc9 100644 --- a/Engine/OverlaySupport.h +++ b/Engine/OverlaySupport.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Engine/EngineFwd.h" + /** * @class An abstract interface for overlay holders. Any OpenGL widget capable of drawing overlays should * implement this interface. diff --git a/Engine/ParallelRenderArgs.cpp b/Engine/ParallelRenderArgs.cpp index f046394d6b..e0a20595bf 100644 --- a/Engine/ParallelRenderArgs.cpp +++ b/Engine/ParallelRenderArgs.cpp @@ -29,6 +29,7 @@ #include "Engine/EffectInstance.h" #include "Engine/Image.h" #include "Engine/Node.h" +#include "Engine/NodeGroup.h" #include "Engine/RotoContext.h" #include "Engine/RotoDrawableItem.h" @@ -595,3 +596,190 @@ NodeFrameRequest::getFrameViewCanonicalRoI(double time, int view, RectD* roi) co *roi = fv->finalData.finalRoi; return true; } + + +/** + * @brief Builds a list with all nodes upstream of the given node (including this node) and all its dependencies through expressions as well (which + * also may be recursive) + **/ +static void getAllUpstreamNodesRecursiveWithDependencies(const boost::shared_ptr& node, std::list >& finalNodes) +{ + if (std::find(finalNodes.begin(), finalNodes.end(), node) != finalNodes.end()) { + return; + } + + finalNodes.push_back(node); + + node->getLiveInstance()->getAllExpressionDependenciesRecursive(finalNodes); + + if (!node->isNodeCreated()) { + return; + } + int maxInputs = node->getMaxInputCount(); + for (int i = 0; i < maxInputs; ++i) { + boost::shared_ptr inputNode = node->getInput(i); + if (inputNode) { + getAllUpstreamNodesRecursiveWithDependencies(inputNode, finalNodes); + } + } + +} + + +ParallelRenderArgsSetter::ParallelRenderArgsSetter(double time, + int view, + bool isRenderUserInteraction, + bool isSequential, + bool canAbort, + U64 renderAge, + const boost::shared_ptr& treeRoot, + const FrameRequestMap* request, + int textureIndex, + const TimeLine* timeline, + const boost::shared_ptr& activeRotoPaintNode, + bool isAnalysis, + bool draftMode, + bool viewerProgressReportEnabled, + const boost::shared_ptr& stats) +: argsMap() +{ + assert(treeRoot); + + bool doNanHandling = appPTR->getCurrentSettings()->isNaNHandlingEnabled(); + + getAllUpstreamNodesRecursiveWithDependencies(treeRoot, nodes); + + for (std::list >::iterator it = nodes.begin(); it != nodes.end(); ++it) { + assert(*it); + + Natron::EffectInstance* liveInstance = (*it)->getLiveInstance(); + assert(liveInstance); + bool duringPaintStrokeCreation = activeRotoPaintNode && (*it)->isDuringPaintStrokeCreation(); + Natron::RenderSafetyEnum safety = (*it)->getCurrentRenderThreadSafety(); + + std::list > rotoPaintNodes; + boost::shared_ptr roto = (*it)->getRotoContext(); + if (roto) { + roto->getRotoPaintTreeNodes(&rotoPaintNodes); + } + + { + U64 nodeHash = 0; + bool hashSet = false; + boost::shared_ptr nodeRequest; + if (request) { + FrameRequestMap::const_iterator foundRequest = request->find(*it); + if (foundRequest != request->end()) { + nodeRequest = foundRequest->second; + nodeHash = nodeRequest->nodeHash; + hashSet = true; + } + } + if (!hashSet) { + nodeHash = (*it)->getHashValue(); + } + + liveInstance->setParallelRenderArgsTLS(time, view, isRenderUserInteraction, isSequential, canAbort, nodeHash, + renderAge,treeRoot, nodeRequest,textureIndex, timeline, isAnalysis,duringPaintStrokeCreation, rotoPaintNodes, safety, doNanHandling, draftMode, viewerProgressReportEnabled, stats); + } + for (std::list >::iterator it2 = rotoPaintNodes.begin(); it2 != rotoPaintNodes.end(); ++it2) { + + boost::shared_ptr childRequest; + U64 nodeHash = 0; + bool hashSet = false; + if (request) { + FrameRequestMap::const_iterator foundRequest = request->find(*it2); + if (foundRequest != request->end()) { + childRequest = foundRequest->second; + nodeHash = childRequest->nodeHash; + hashSet = true; + } + } + if (!hashSet) { + nodeHash = (*it2)->getHashValue(); + } + + (*it2)->getLiveInstance()->setParallelRenderArgsTLS(time, view, isRenderUserInteraction, isSequential, canAbort, nodeHash, renderAge, treeRoot, childRequest, textureIndex, timeline, isAnalysis, activeRotoPaintNode && (*it2)->isDuringPaintStrokeCreation(), NodeList(), (*it2)->getCurrentRenderThreadSafety(), doNanHandling, draftMode, viewerProgressReportEnabled,stats); + } + + if ((*it)->isMultiInstance()) { + + ///If the node has children, set the thread-local storage on them too, even if they do not render, it can be useful for expressions + ///on parameters. + std::list > children; + (*it)->getChildrenMultiInstance(&children); + for (std::list >::iterator it2 = children.begin(); it2!=children.end(); ++it2) { + + boost::shared_ptr childRequest; + U64 nodeHash = 0; + bool hashSet = false; + if (request) { + FrameRequestMap::const_iterator foundRequest = request->find(*it2); + if (foundRequest != request->end()) { + childRequest = foundRequest->second; + nodeHash = childRequest->nodeHash; + hashSet = true; + } + } + if (!hashSet) { + nodeHash = (*it2)->getHashValue(); + } + + assert(*it2); + Natron::EffectInstance* childLiveInstance = (*it2)->getLiveInstance(); + assert(childLiveInstance); + Natron::RenderSafetyEnum childSafety = (*it2)->getCurrentRenderThreadSafety(); + childLiveInstance->setParallelRenderArgsTLS(time, view, isRenderUserInteraction, isSequential, canAbort, nodeHash, renderAge,treeRoot, childRequest, textureIndex, timeline, isAnalysis, false, std::list >(), childSafety, doNanHandling, draftMode, viewerProgressReportEnabled,stats); + + } + } + + + /* NodeGroup* isGrp = dynamic_cast((*it)->getLiveInstance()); + if (isGrp) { + isGrp->setParallelRenderArgs(time, view, isRenderUserInteraction, isSequential, canAbort, renderAge, treeRoot, request, textureIndex, timeline, activeRotoPaintNode, isAnalysis, draftMode, viewerProgressReportEnabled,stats); + }*/ + + } + +} + +ParallelRenderArgsSetter::ParallelRenderArgsSetter(const std::map,ParallelRenderArgs >& args) +: argsMap(args) +{ + for (std::map,ParallelRenderArgs >::iterator it = argsMap.begin(); it != argsMap.end(); ++it) { + it->first->getLiveInstance()->setParallelRenderArgsTLS(it->second); + } +} + +ParallelRenderArgsSetter::~ParallelRenderArgsSetter() +{ + + for (NodeList::iterator it = nodes.begin(); it != nodes.end(); ++it) { + if (!(*it) || !(*it)->getLiveInstance()) { + continue; + } + (*it)->getLiveInstance()->invalidateParallelRenderArgsTLS(); + + if ((*it)->isMultiInstance()) { + + ///If the node has children, set the thread-local storage on them too, even if they do not render, it can be useful for expressions + ///on parameters. + NodeList children; + (*it)->getChildrenMultiInstance(&children); + for (NodeList::iterator it2 = children.begin(); it2!=children.end(); ++it2) { + (*it2)->getLiveInstance()->invalidateParallelRenderArgsTLS(); + + } + } + + /* NodeGroup* isGrp = dynamic_cast((*it)->getLiveInstance()); + if (isGrp) { + isGrp->invalidateParallelRenderArgs(); + }*/ + } + + for (std::map,ParallelRenderArgs >::iterator it = argsMap.begin(); it != argsMap.end(); ++it) { + it->first->getLiveInstance()->invalidateParallelRenderArgsTLS(); + } +} diff --git a/Engine/ParallelRenderArgs.h b/Engine/ParallelRenderArgs.h index c3e4d50fdb..29d16101d0 100644 --- a/Engine/ParallelRenderArgs.h +++ b/Engine/ParallelRenderArgs.h @@ -36,6 +36,7 @@ #include "Global/GlobalDefines.h" #include "Engine/RectD.h" +#include "Engine/EngineFwd.h" //This controls how many frames a plug-in can pre-fetch (per view and per input) @@ -43,18 +44,6 @@ //do not all stick altogether in memory #define NATRON_MAX_FRAMES_NEEDED_PRE_FETCHING 4 -class RectI; -class TimeLine; -namespace Natron { - class EffectInstance; - class Node; -} -namespace Transform { - struct Matrix3x3; -} -class RenderStats; - - typedef std::map RoIMap; // RoIs are in canonical coordinates typedef std::map > > FramesNeededMap; @@ -176,6 +165,9 @@ struct ParallelRenderArgs } }; + + + struct FrameViewPair { double time; int view; @@ -264,5 +256,40 @@ struct NodeFrameRequest typedef std::map,boost::shared_ptr > FrameRequestMap; +class ParallelRenderArgsSetter +{ + std::map,ParallelRenderArgs > argsMap; + std::list > nodes; + +public: + + /** + * @brief Set the TLS for rendering a frame on the tree upstream of treeRoot (including it) and all nodes that + * can be reached through expressions. + * We do this because TLS is needed to know the correct frame, view at which the frame is evaluated (i.e rendered) + * even in nodes that do not belong in the tree. The reason why is because the nodes in the tree may have parameters + * relying on other nodes that do not belong in the tree through expressions. + **/ + ParallelRenderArgsSetter(double time, + int view, + bool isRenderUserInteraction, + bool isSequential, + bool canAbort, + U64 renderAge, + const boost::shared_ptr& treeRoot, + const FrameRequestMap* request, + int textureIndex, + const TimeLine* timeline, + const boost::shared_ptr& activeRotoPaintNode, + bool isAnalysis, + bool draftMode, + bool viewerProgressReportEnabled, + const boost::shared_ptr& stats); + + ParallelRenderArgsSetter(const std::map,ParallelRenderArgs >& args); + + virtual ~ParallelRenderArgsSetter(); +}; + #endif // PARALLELRENDERARGS_H diff --git a/Engine/ParameterWrapper.cpp b/Engine/ParameterWrapper.cpp index bc797ab871..ef7e1e8d3b 100644 --- a/Engine/ParameterWrapper.cpp +++ b/Engine/ParameterWrapper.cpp @@ -100,6 +100,12 @@ Param::setVisible(bool visible) getInternalKnob()->setSecret(!visible); } +void +Param::setVisibleByDefault(bool visible) +{ + getInternalKnob()->setSecretByDefault(!visible); +} + bool Param::getIsEnabled(int dimension) const { @@ -112,6 +118,12 @@ Param::setEnabled(bool enabled,int dimension) getInternalKnob()->setEnabled(dimension, enabled); } +void +Param::setEnabledByDefault(bool enabled) +{ + getInternalKnob()->setDefaultAllDimensionsEnabled(enabled); +} + bool Param::getIsPersistant() const { @@ -256,6 +268,21 @@ Param::curve(double time, int dimension) const return getInternalKnob()->getRawCurveValueAt(time, dimension); } +bool +Param::setAsAlias(Param* other) +{ + if (!other) { + return false; + } + boost::shared_ptr otherKnob = other->_knob.lock(); + boost::shared_ptr thisKnob = getInternalKnob(); + if (!otherKnob || !thisKnob || otherKnob->typeName() != thisKnob->typeName() || + otherKnob->getDimension() != thisKnob->getDimension()) { + return false; + } + return otherKnob->setKnobAsAliasOfThis(thisKnob, true); +} + AnimatedParam::AnimatedParam(const boost::shared_ptr& knob) : Param(knob) { diff --git a/Engine/ParameterWrapper.h b/Engine/ParameterWrapper.h index 43774d37de..fee9cb7721 100644 --- a/Engine/ParameterWrapper.h +++ b/Engine/ParameterWrapper.h @@ -37,6 +37,7 @@ #include "Engine/KnobTypes.h" #include "Engine/KnobFile.h" +#include "Engine/EngineFwd.h" class Param { @@ -97,6 +98,8 @@ class Param **/ void setVisible(bool visible); + void setVisibleByDefault(bool visible); + /** * @brief Returns whether the given dimension is enabled, i.e: whether the user can interact with it or not. **/ @@ -107,6 +110,8 @@ class Param **/ void setEnabled(bool enabled,int dimension = 0); + void setEnabledByDefault(bool enabled = 0); + /** * @brief Returns whether this parameter is persistant or not. A persistant parameter will be saved into the project. **/ @@ -171,6 +176,8 @@ class Param **/ double curve(double time, int dimension = 0) const; + bool setAsAlias(Param* other); + protected: /** diff --git a/Engine/Plugin.h b/Engine/Plugin.h index 34f53e61a5..c11947583d 100644 --- a/Engine/Plugin.h +++ b/Engine/Plugin.h @@ -37,22 +37,9 @@ #endif #include "Global/Enums.h" +#include "Engine/EngineFwd.h" -namespace OFX{ - namespace Host{ - namespace ImageEffect{ - class ImageEffectPlugin; - class Descriptor; - } - } -} - -class QMutex; -namespace Natron { -class LibraryBinary; -} - class PluginGroupNode { QString _id; diff --git a/Engine/PluginMemory.h b/Engine/PluginMemory.h index 51ca4a5d16..ef3db0f4cf 100644 --- a/Engine/PluginMemory.h +++ b/Engine/PluginMemory.h @@ -29,10 +29,8 @@ #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif -namespace Natron { -class EffectInstance; -} +#include "Engine/EngineFwd.h" class PluginMemory { diff --git a/Engine/ProcessHandler.h b/Engine/ProcessHandler.h index 519bb6fd25..10c3b73516 100644 --- a/Engine/ProcessHandler.h +++ b/Engine/ProcessHandler.h @@ -32,19 +32,11 @@ CLANG_DIAG_OFF(deprecated) #include #include CLANG_DIAG_ON(deprecated) + #include "Global/GlobalDefines.h" -//natron -class AppInstance; -namespace Natron { -class OutputEffectInstance; -} - -//qt -class QLocalServer; -class QLocalSocket; -class QMutex; -class QWaitCondition; +#include "Engine/EngineFwd.h" + /** * @brief This class represents a background render process. It starts a render and reports progress via a diff --git a/Engine/Project.cpp b/Engine/Project.cpp index fb51c9c967..a705e30b05 100644 --- a/Engine/Project.cpp +++ b/Engine/Project.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #ifdef __NATRON_WIN32__ @@ -246,7 +247,10 @@ Project::loadProject(const QString & path, bool Project::loadProjectInternal(const QString & path, - const QString & name,bool isAutoSave,bool isUntitledAutosave, bool* mustSave) + const QString & name, + bool isAutoSave, + bool isUntitledAutosave, + bool* mustSave) { Natron::FlagSetter loadingProjectRAII(true,&_imp->isLoadingProject,&_imp->isLoadingProjectMutex); @@ -333,10 +337,10 @@ Project::loadProjectInternal(const QString & path, if (isAutoSave) { _imp->autoSetProjectFormat = false; if (!isUntitledAutosave) { - QString projectName(_imp->getProjectFilename().c_str()); - int found = projectName.lastIndexOf(".autosave"); + QString projectFilename(_imp->getProjectFilename().c_str()); + int found = projectFilename.lastIndexOf(".autosave"); if (found != -1) { - _imp->setProjectFilename(projectName.left(found).toStdString()); + _imp->setProjectFilename(projectFilename.left(found).toStdString()); } _imp->hasProjectBeenSavedByUser = true; } else { @@ -348,11 +352,12 @@ Project::loadProjectInternal(const QString & path, _imp->ageSinceLastSave = QDateTime(); _imp->lastAutoSaveFilePath = filePath; - QString projectName(_imp->getProjectFilename().c_str()); - Q_EMIT projectNameChanged(projectName + " (*)"); + QString projectPath(_imp->getProjectPath().c_str()); + QString projectFilename(_imp->getProjectFilename().c_str()); + Q_EMIT projectNameChanged(projectPath + projectFilename, true); } else { - Q_EMIT projectNameChanged(name); + Q_EMIT projectNameChanged(path + name, false); } ///Try to take the project lock by creating a lock file @@ -592,14 +597,15 @@ Project::saveProjectInternal(const QString & path, _imp->hasProjectBeenSavedByUser = true; _imp->ageSinceLastSave = time; } - Q_EMIT projectNameChanged(name); //< notify the gui so it can update the title + Q_EMIT projectNameChanged(path + name, false); //< notify the gui so it can update the title //Create the lock file corresponding to the project createLockFile(); } else if (updateProjectProperties) { if (!isRenderSave) { - QString projectName(_imp->getProjectFilename().c_str()); - Q_EMIT projectNameChanged(projectName + " (*)"); + QString projectPath(_imp->getProjectPath().c_str()); + QString projectFilename(_imp->getProjectFilename().c_str()); + Q_EMIT projectNameChanged(projectPath + projectFilename, true); } } if (updateProjectProperties) { @@ -1188,7 +1194,7 @@ Project::createProjectViews(const std::vector& views) } QString -Project::getProjectName() const +Project::getProjectFilename() const { return _imp->getProjectFilename().c_str(); } @@ -1286,13 +1292,20 @@ Project::onKnobValueChanged(KnobI* knob, bool /*originatedFromMainThread*/) { if ( knob == _imp->viewsList.get() ) { + + /** + * All cache entries are linked to a view index which may no longer be correct since the user changed the project settings. + * The only way to overcome this is to wipe the cache. + **/ + appPTR->clearAllCaches(); + std::vector viewNames = getProjectViewNames(); getApp()->setupViewersForViews(viewNames); if (reason == Natron::eValueChangedReasonUserEdited) { ///views change, notify all OneView nodes via getClipPreferences forceComputeInputDependentDataOnAllTrees(); } - + } else if (knob == _imp->setupForStereoButton.get()) { setupProjectForStereo(); } else if ( knob == _imp->formatKnob.get() ) { @@ -1364,7 +1377,7 @@ QString Project::getLockAbsoluteFilePath() const { QString projectPath(_imp->getProjectPath().c_str()); - QString projectName(_imp->getProjectFilename().c_str()); + QString projectFilename(_imp->getProjectFilename().c_str()); if (projectPath.isEmpty()) { return QString(); @@ -1372,7 +1385,7 @@ Project::getLockAbsoluteFilePath() const if (!projectPath.endsWith('/')) { projectPath.append('/'); } - QString lockFilePath = projectPath + projectName + ".lock"; + QString lockFilePath = projectPath + projectFilename + ".lock"; return lockFilePath; } @@ -1393,7 +1406,8 @@ Project::createLockFile() QString curDateStr = now.toString(); ts << curDateStr << '\n' << lastAuthor << '\n' - << QCoreApplication::applicationPid(); + << QCoreApplication::applicationPid() << '\n' + << QHostInfo::localHostName(); } void @@ -1406,7 +1420,12 @@ Project::removeLockFile() } bool -Project::getLockFileInfos(const QString& projectPath,const QString& projectName,QString* authorName,QString* lastSaveDate,qint64* appPID) const +Project::getLockFileInfos(const QString& projectPath, + const QString& projectName, + QString* authorName, + QString* lastSaveDate, + QString* host, + qint64* appPID) const { QString realPath = projectPath; if (!realPath.endsWith('/')) { @@ -1434,6 +1453,12 @@ Project::getLockFileInfos(const QString& projectPath,const QString& projectName, } else { return false; } + // host is optional and was added later + if (!ts.atEnd()) { + *host = ts.readLine(); + } else { + *host = tr("unknown host"); + } return true; } @@ -1454,13 +1479,13 @@ Project::removeLastAutosave() * a oldProject.ntp.autosave file next to it that belonged to the old project, make sure it gets removed too */ QString projectPath(_imp->getProjectPath().c_str()); - QString projectName(_imp->getProjectFilename().c_str()); + QString projectFilename(_imp->getProjectFilename().c_str()); if (!projectPath.endsWith('/')) { projectPath.append('/'); } - QString autoSaveFilePath = projectPath + projectName + ".autosave"; + QString autoSaveFilePath = projectPath + projectFilename + ".autosave"; if (QFile::exists(autoSaveFilePath)) { QFile::remove(autoSaveFilePath); } @@ -1520,12 +1545,14 @@ Project::reset(bool aboutToQuit) QString lockFilePath = getLockAbsoluteFilePath(); QString projectPath(_imp->getProjectPath().c_str()); - QString projectName(_imp->getProjectFilename().c_str()); + QString projectFilename(_imp->getProjectFilename().c_str()); ///Remove the lock file if we own it if (QFile::exists(lockFilePath)) { - QString author,lastsave; + QString author; + QString lastsave; + QString host; qint64 pid; - if (getLockFileInfos(projectPath, projectName, &author, &lastsave, &pid)) { + if (getLockFileInfos(projectPath, projectFilename, &author, &lastsave, &host, &pid)) { if (pid == QCoreApplication::applicationPid()) { QFile::remove(lockFilePath); } @@ -1547,7 +1574,7 @@ Project::reset(bool aboutToQuit) } _imp->timeline->removeAllKeyframesIndicators(); - Q_EMIT projectNameChanged(NATRON_PROJECT_UNTITLED); + Q_EMIT projectNameChanged(NATRON_PROJECT_UNTITLED, false); const std::vector > & knobs = getKnobs(); diff --git a/Engine/Project.h b/Engine/Project.h index 072926138c..dd42eafc21 100644 --- a/Engine/Project.h +++ b/Engine/Project.h @@ -41,21 +41,16 @@ CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Global/GlobalDefines.h" + #include "Engine/Knob.h" #include "Engine/Format.h" #include "Engine/TimeLine.h" #include "Engine/NodeGroup.h" +#include "Engine/EngineFwd.h" + -class QString; -class QDateTime; -class AppInstance; -class ProjectSerialization; -class KnobSerialization; -class ProjectGui; -class AddFormatDialog; namespace Natron { -class Node; -class OutputEffectInstance; + struct ProjectPrivate; class Project @@ -116,7 +111,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON bool isLoadingProjectInternal() const; - QString getProjectName() const WARN_UNUSED_RETURN; + QString getProjectFilename() const WARN_UNUSED_RETURN; QString getLastAutoSaveFilePath() const; @@ -189,7 +184,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON QString getLockAbsoluteFilePath() const; void createLockFile(); void removeLockFile(); - bool getLockFileInfos(const QString& projectPath,const QString& projectName,QString* authorName,QString* lastSaveDate,qint64* appPID) const; + bool getLockFileInfos(const QString& projectPath, const QString& projectName, QString* authorName, QString* lastSaveDate, QString* host, qint64* appPID) const; virtual bool isProject() const OVERRIDE { @@ -330,7 +325,7 @@ public Q_SLOTS: void autoPreviewChanged(bool); - void projectNameChanged(QString); + void projectNameChanged(QString name, bool modified); void knobsInitialized(); diff --git a/Engine/ProjectPrivate.cpp b/Engine/ProjectPrivate.cpp index a4adafc39b..73558674ad 100644 --- a/Engine/ProjectPrivate.cpp +++ b/Engine/ProjectPrivate.cpp @@ -173,7 +173,7 @@ ProjectPrivate::restoreFromSerialization(const ProjectSerialization & obj, } /// 2) restore the timeline - timeline->seekFrame(obj.getCurrentTime(), false, 0, Natron::eTimelineChangeReasonPlaybackSeek); + timeline->seekFrame(obj.getCurrentTime(), false, 0, Natron::eTimelineChangeReasonOtherSeek); /// 3) Restore the nodes diff --git a/Engine/ProjectPrivate.h b/Engine/ProjectPrivate.h index dd283afe86..9763f072b0 100644 --- a/Engine/ProjectPrivate.h +++ b/Engine/ProjectPrivate.h @@ -44,16 +44,9 @@ CLANG_DIAG_ON(uninitialized) #include "Engine/KnobFile.h" #include "Engine/KnobFactory.h" #include "Engine/ThreadStorage.h" +#include "Engine/EngineFwd.h" -class QTimer; -class TimeLine; -class NodeSerialization; -class ProjectSerialization; -class KnobFile; namespace Natron { -class Node; -class OutputEffectInstance; -class Project; inline QString generateStringFromFormat(const Format & f) diff --git a/Engine/ProjectSerialization.h b/Engine/ProjectSerialization.h index 2994f7f891..90b075c73b 100644 --- a/Engine/ProjectSerialization.h +++ b/Engine/ProjectSerialization.h @@ -55,6 +55,7 @@ GCC_DIAG_ON(unused-parameter) #include "Engine/NodeSerialization.h" #include "Engine/NodeGroupSerialization.h" #include "Engine/KnobSerialization.h" +#include "Engine/EngineFwd.h" #define PROJECT_SERIALIZATION_INTRODUCES_NATRON_VERSION 2 #define PROJECT_SERIALIZATION_REMOVES_NODE_COUNTERS 3 @@ -62,7 +63,6 @@ GCC_DIAG_ON(unused-parameter) #define PROJECT_SERIALIZATION_INTRODUCES_GROUPS 5 #define PROJECT_SERIALIZATION_VERSION PROJECT_SERIALIZATION_INTRODUCES_GROUPS -class AppInstance; class ProjectSerialization { NodeCollectionSerialization _nodes; diff --git a/Engine/RectD.h b/Engine/RectD.h index e9658c7e5f..5d87b13f1e 100644 --- a/Engine/RectD.h +++ b/Engine/RectD.h @@ -36,9 +36,9 @@ #include "Global/GlobalDefines.h" #include "Global/Macros.h" -GCC_DIAG_OFF(strict-overflow) +#include "Engine/EngineFwd.h" -class RectI; +GCC_DIAG_OFF(strict-overflow) class RectD { diff --git a/Engine/RectDSerialization.h b/Engine/RectDSerialization.h index 091e07b735..bbaaea7840 100644 --- a/Engine/RectDSerialization.h +++ b/Engine/RectDSerialization.h @@ -37,6 +37,8 @@ GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_ON GCC_DIAG_ON(unused-parameter) #endif +#include "Engine/EngineFwd.h" + template void RectD::serialize(Archive & ar, const unsigned int version) diff --git a/Engine/RectI.h b/Engine/RectI.h index a147306fd4..3d02961778 100644 --- a/Engine/RectI.h +++ b/Engine/RectI.h @@ -36,9 +36,10 @@ #include "Global/GlobalDefines.h" #include "Global/Macros.h" +#include "Engine/EngineFwd.h" + GCC_DIAG_OFF(strict-overflow) -class RectD; /** * @brief A rectangle where x1 < x2 and y1 < y2 such as width() == (x2 - x1) && height() == (y2 - y1) diff --git a/Engine/RectISerialization.h b/Engine/RectISerialization.h index b009621421..72afac91b5 100644 --- a/Engine/RectISerialization.h +++ b/Engine/RectISerialization.h @@ -37,6 +37,9 @@ GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_ON GCC_DIAG_ON(unused-parameter) #endif +#include "Engine/EngineFwd.h" + + template void RectI::serialize(Archive & ar, const unsigned int version) diff --git a/Engine/RenderStats.h b/Engine/RenderStats.h index 1c42fb7a32..ce5be7ff34 100644 --- a/Engine/RenderStats.h +++ b/Engine/RenderStats.h @@ -36,16 +36,13 @@ #include #endif - - #include "Global/GlobalDefines.h" #include "Engine/RectI.h" #include "Engine/RectD.h" +#include "Engine/EngineFwd.h" + -namespace Natron { - class Node; -} /** * @brief Holds render infos for one frame for one node. Not MT-safe: MT-safety is handled by RenderStats. **/ diff --git a/Engine/RotoContext.cpp b/Engine/RotoContext.cpp index 03f6b6054b..4e168cb95d 100644 --- a/Engine/RotoContext.cpp +++ b/Engine/RotoContext.cpp @@ -110,17 +110,13 @@ RotoContext::isRotoPaint() const } void -RotoContext::setStrokeBeingPainted(const boost::shared_ptr& stroke) +RotoContext::setWhileCreatingPaintStrokeOnMergeNodes(bool b) { + getNode()->setWhileCreatingPaintStroke(b); QMutexLocker k(&_imp->rotoContextMutex); - _imp->strokeBeingPainted = stroke; -} - -boost::shared_ptr -RotoContext::getStrokeBeingPainted() const -{ - QMutexLocker k(&_imp->rotoContextMutex); - return _imp->strokeBeingPainted; + for (std::list >::iterator it = _imp->globalMergeNodes.begin(); it != _imp->globalMergeNodes.end(); ++it) { + (*it)->setWhileCreatingPaintStroke(b); + } } boost::shared_ptr @@ -131,12 +127,7 @@ RotoContext::getRotoPaintBottomMergeNode() const return boost::shared_ptr(); } - boost::shared_ptr strokeBeingPainted; - { - QMutexLocker k(&_imp->rotoContextMutex); - strokeBeingPainted = _imp->strokeBeingPainted; - } - if (!strokeBeingPainted && isRotoPaintTreeConcatenatableInternal(items)) { + if (isRotoPaintTreeConcatenatableInternal(items)) { QMutexLocker k(&_imp->rotoContextMutex); if (!_imp->globalMergeNodes.empty()) { return _imp->globalMergeNodes.front(); @@ -498,7 +489,6 @@ RotoContext::makeStroke(Natron::RotoStrokeType type,const std::string& baseName, parentLayer->insertItem(curve,0); } curve->createNodes(); - _imp->strokeBeingPainted = curve; _imp->lastInsertedItem = curve; @@ -811,6 +801,14 @@ RotoContext::getItemsRegionOfDefinition(const std::list activeRotoPaintNode; + boost::shared_ptr activeStroke; + bool isDrawing; + getNode()->getApp()->getActiveRotoDrawingStroke(&activeRotoPaintNode, &activeStroke,&isDrawing); + if (!isDrawing) { + activeStroke.reset(); + } + QMutexLocker l(&_imp->rotoContextMutex); for (double t = startTime; t <= endTime; t+= mbFrameStep) { bool first = true; @@ -835,7 +833,7 @@ RotoContext::getItemsRegionOfDefinition(const std::listisActivated(time)) { - if (isStroke == _imp->strokeBeingPainted.get()) { + if (isStroke == activeStroke.get()) { strokeRod = isStroke->getMergeNode()->getPaintStrokeRoD_duringPainting(); } else { strokeRod = isStroke->getBoundingBox(t); @@ -1671,7 +1669,7 @@ RotoContext::goToPreviousKeyframe() if (minimum != INT_MIN) { getNode()->getApp()->setLastViewerUsingTimeline(boost::shared_ptr()); - getNode()->getApp()->getTimeLine()->seekFrame(minimum, false, NULL, Natron::eTimelineChangeReasonPlaybackSeek); + getNode()->getApp()->getTimeLine()->seekFrame(minimum, false, NULL, Natron::eTimelineChangeReasonOtherSeek); } } @@ -1704,7 +1702,7 @@ RotoContext::goToNextKeyframe() } if (maximum != INT_MAX) { getNode()->getApp()->setLastViewerUsingTimeline(boost::shared_ptr()); - getNode()->getApp()->getTimeLine()->seekFrame(maximum, false, NULL,Natron::eTimelineChangeReasonPlaybackSeek); + getNode()->getApp()->getTimeLine()->seekFrame(maximum, false, NULL,Natron::eTimelineChangeReasonOtherSeek); } } @@ -3855,11 +3853,12 @@ void RotoContext::changeItemScriptName(const std::string& oldFullyQualifiedName,const std::string& newFullyQUalifiedName) { std::string appID = getNode()->getApp()->getAppIDString(); - std::string nodeName = appID + "." + getNode()->getFullyQualifiedName(); + std::string nodeName = getNode()->getFullyQualifiedName(); + std::string nodeFullName = appID + "." + nodeName; std::string err; - std::string declStr = nodeName + ".roto." + newFullyQUalifiedName + " = " + nodeName + ".roto." + oldFullyQualifiedName + "\n"; - std::string delStr = "del " + nodeName + ".roto." + oldFullyQualifiedName + "\n"; + std::string declStr = nodeFullName + ".roto." + newFullyQUalifiedName + " = " + nodeFullName + ".roto." + oldFullyQualifiedName + "\n"; + std::string delStr = "del " + nodeFullName + ".roto." + oldFullyQualifiedName + "\n"; std::string script = declStr + delStr; if (!appPTR->isBackground()) { getNode()->getApp()->printAutoDeclaredVariable(script); @@ -3879,9 +3878,10 @@ RotoContext::removeItemAsPythonField(const boost::shared_ptr& item) return; } std::string appID = getNode()->getApp()->getAppIDString(); - std::string nodeName = appID + "." + getNode()->getFullyQualifiedName(); + std::string nodeName = getNode()->getFullyQualifiedName(); + std::string nodeFullName = appID + "." + nodeName; std::string err; - std::string script = "del " + nodeName + ".roto." + item->getFullyQualifiedName() + "\n"; + std::string script = "del " + nodeFullName + ".roto." + item->getFullyQualifiedName() + "\n"; if (!appPTR->isBackground()) { getNode()->getApp()->printAutoDeclaredVariable(script); } @@ -4022,8 +4022,9 @@ void RotoContext::declareItemAsPythonField(const boost::shared_ptr& item) { std::string appID = getNode()->getApp()->getAppIDString(); - std::string nodeName = appID + "." + getNode()->getFullyQualifiedName(); - + std::string nodeName = getNode()->getFullyQualifiedName(); + std::string nodeFullName = appID + "." + nodeName; + RotoStrokeItem* isStroke = dynamic_cast(item.get()); if (isStroke) { ///Strokes are unsupported in Python currently @@ -4032,8 +4033,8 @@ RotoContext::declareItemAsPythonField(const boost::shared_ptr& item) RotoLayer* isLayer = dynamic_cast(item.get()); std::string err; - std::string script = nodeName + ".roto." + item->getFullyQualifiedName() + " = " + - nodeName + ".roto.getItemByName(\"" + item->getScriptName() + "\")\n"; + std::string script = (nodeFullName + ".roto." + item->getFullyQualifiedName() + " = " + + nodeFullName + ".roto.getItemByName(\"" + item->getScriptName() + "\")\n"); if (!appPTR->isBackground()) { getNode()->getApp()->printAutoDeclaredVariable(script); } diff --git a/Engine/RotoContext.h b/Engine/RotoContext.h index 1b71fdd87f..89470c5aec 100644 --- a/Engine/RotoContext.h +++ b/Engine/RotoContext.h @@ -37,66 +37,26 @@ #include #endif -#include "Global/GlobalDefines.h" -#include "Engine/FitCurve.h" -#include "Engine/RotoItem.h" - CLANG_DIAG_OFF(deprecated-declarations) #include #include #include CLANG_DIAG_ON(deprecated-declarations) -#define kRotoLayerBaseName "Layer" -#define kRotoBezierBaseName "Bezier" -#define kRotoOpenBezierBaseName "Pencil" -#define kRotoEllipseBaseName "Ellipse" -#define kRotoRectangleBaseName "Rectangle" -#define kRotoPaintBrushBaseName "Brush" -#define kRotoPaintEraserBaseName "Eraser" -#define kRotoPaintBlurBaseName "Blur" -#define kRotoPaintSmearBaseName "Smear" -#define kRotoPaintSharpenBaseName "Sharpen" -#define kRotoPaintCloneBaseName "Clone" -#define kRotoPaintRevealBaseName "Reveal" -#define kRotoPaintDodgeBaseName "Dodge" -#define kRotoPaintBurnBaseName "Burn" + +#include "Global/GlobalDefines.h" + +#include "Engine/FitCurve.h" +#include "Engine/RotoItem.h" +#include "Engine/EngineFwd.h" + //#define NATRON_ROTO_ENABLE_MOTION_BLUR -namespace Natron { -class Image; -class ImageComponents; -class Node; -} -namespace boost { namespace serialization { class access; } } - -class RectI; -class RectD; -class KnobI; -class KnobBool; -class KnobDouble; -class KnobInt; -class KnobChoice; -class KnobColor; -typedef struct _cairo_pattern cairo_pattern_t; - -class Curve; -class Bezier; -class RotoItemSerialization; -class BezierCP; /** * @class A base class for all items made by the roto context **/ -class RotoContext; -class RotoLayer; -class RotoStrokeItem; -class RotoDrawableItem; - -namespace Transform { -struct Matrix3x3; -} @@ -428,9 +388,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; + + void setWhileCreatingPaintStrokeOnMergeNodes(bool b); /** * @brief First searches through the selected layer which one is the deepest in the hierarchy. diff --git a/Engine/RotoContextPrivate.h b/Engine/RotoContextPrivate.h index 8fe7c4a91d..8ec9666b4d 100644 --- a/Engine/RotoContextPrivate.h +++ b/Engine/RotoContextPrivate.h @@ -59,6 +59,7 @@ #include "Engine/Transform.h" #include "Engine/MergingEnum.h" #include "Engine/RotoPaint.h" +#include "Engine/EngineFwd.h" #define ROTO_DEFAULT_OPACITY 1. #define ROTO_DEFAULT_FEATHER 1.5 @@ -346,10 +347,6 @@ #define kRotoShutterCustomOffsetParamHint "If the Shutter Offset parameter is set to Custom then this parameter controls the frame at " \ "which the shutter opens. The value is an offset in frames to the current frame, e.g: -1 would open the shutter 1 frame before the current frame." -class Bezier; - - -class BezierCP; struct BezierPrivate @@ -1327,7 +1324,6 @@ struct RotoContextPrivate std::list > selectedItems; boost::shared_ptr lastInsertedItem; boost::shared_ptr lastLockedItem; - boost::shared_ptr strokeBeingPainted; //Used to prevent 2 threads from writing the same image in the rotocontext mutable QMutex cacheAccessMutex; diff --git a/Engine/RotoContextSerialization.h b/Engine/RotoContextSerialization.h index e49943769d..bceb1006d8 100644 --- a/Engine/RotoContextSerialization.h +++ b/Engine/RotoContextSerialization.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_OFF GCC_DIAG_OFF(unused-parameter) @@ -45,6 +47,8 @@ GCC_DIAG_ON(unused-parameter) #include "Engine/RotoLayer.h" #include "Engine/RotoLayerSerialization.h" #include "Engine/RotoContextPrivate.h" +#include "Engine/EngineFwd.h" + #define ROTO_CTX_REMOVE_COUNTERS 2 #define ROTO_CTX_VERSION ROTO_CTX_REMOVE_COUNTERS diff --git a/Engine/RotoDrawableItem.cpp b/Engine/RotoDrawableItem.cpp index 0c9f23c258..291478743b 100644 --- a/Engine/RotoDrawableItem.cpp +++ b/Engine/RotoDrawableItem.cpp @@ -135,7 +135,7 @@ RotoDrawableItem::setNodesThreadSafetyForRotopainting() assert(boost::dynamic_pointer_cast(boost::dynamic_pointer_cast(shared_from_this()))); getContext()->getNode()->setRenderThreadSafety(Natron::eRenderSafetyInstanceSafe); - getContext()->getNode()->setWhileCreatingPaintStroke(true); + getContext()->setWhileCreatingPaintStrokeOnMergeNodes(true); if (_imp->effectNode) { _imp->effectNode->setWhileCreatingPaintStroke(true); _imp->effectNode->setRenderThreadSafety(Natron::eRenderSafetyInstanceSafe); @@ -160,7 +160,7 @@ RotoDrawableItem::createNodes(bool connectNodes) const std::list >& knobs = getKnobs(); for (std::list >::const_iterator it = knobs.begin(); it != knobs.end(); ++it) { - QObject::connect((*it)->getSignalSlotHandler().get(), SIGNAL(updateDependencies(int,int)), this, SLOT(onRotoKnobChanged(int,int))); + QObject::connect((*it)->getSignalSlotHandler().get(), SIGNAL(valueChanged(int,int)), this, SLOT(onRotoKnobChanged(int,int))); } boost::shared_ptr context = getContext(); diff --git a/Engine/RotoDrawableItem.h b/Engine/RotoDrawableItem.h index 60d9d7210b..6fbc1901c7 100644 --- a/Engine/RotoDrawableItem.h +++ b/Engine/RotoDrawableItem.h @@ -37,64 +37,22 @@ #include #endif -#include "Global/GlobalDefines.h" -#include "Engine/FitCurve.h" -#include "Engine/CacheEntryHolder.h" -#include "Engine/RotoItem.h" - CLANG_DIAG_OFF(deprecated-declarations) #include #include #include CLANG_DIAG_ON(deprecated-declarations) -#define kRotoLayerBaseName "Layer" -#define kRotoBezierBaseName "Bezier" -#define kRotoOpenBezierBaseName "Pencil" -#define kRotoBSplineBaseName "BSpline" -#define kRotoEllipseBaseName "Ellipse" -#define kRotoRectangleBaseName "Rectangle" -#define kRotoPaintBrushBaseName "Brush" -#define kRotoPaintEraserBaseName "Eraser" -#define kRotoPaintBlurBaseName "Blur" -#define kRotoPaintSmearBaseName "Smear" -#define kRotoPaintSharpenBaseName "Sharpen" -#define kRotoPaintCloneBaseName "Clone" -#define kRotoPaintRevealBaseName "Reveal" -#define kRotoPaintDodgeBaseName "Dodge" -#define kRotoPaintBurnBaseName "Burn" - -namespace Natron { -class Image; -class ImageComponents; -class Node; -} -namespace boost { namespace serialization { class access; } } - -class RectI; -class RectD; -class KnobI; -class KnobBool; -class KnobDouble; -class KnobInt; -class KnobChoice; -class KnobColor; -typedef struct _cairo_pattern cairo_pattern_t; - -class Curve; -class Bezier; -class RotoItemSerialization; -class BezierCP; +#include "Global/GlobalDefines.h" +#include "Engine/FitCurve.h" +#include "Engine/CacheEntryHolder.h" +#include "Engine/RotoItem.h" +#include "Engine/EngineFwd.h" + /** * @class A base class for all items made by the roto context **/ -class RotoContext; -class RotoLayer; - -namespace Transform { -struct Matrix3x3; -} /** * @brief Base class for all drawable items diff --git a/Engine/RotoDrawableItemSerialization.h b/Engine/RotoDrawableItemSerialization.h index dcf0925ee2..51fc205763 100644 --- a/Engine/RotoDrawableItemSerialization.h +++ b/Engine/RotoDrawableItemSerialization.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_OFF GCC_DIAG_OFF(unused-parameter) @@ -45,6 +47,8 @@ GCC_DIAG_ON(unused-parameter) #include "Engine/RotoLayer.h" #include "Engine/RotoContextPrivate.h" #include "Engine/RotoItemSerialization.h" +#include "Engine/EngineFwd.h" + #define ROTO_DRAWABLE_ITEM_INTRODUCES_COMPOSITING 2 #define ROTO_DRAWABLE_ITEM_REMOVES_INVERTED 3 diff --git a/Engine/RotoItem.h b/Engine/RotoItem.h index d0db9583dd..0f7b6632bb 100644 --- a/Engine/RotoItem.h +++ b/Engine/RotoItem.h @@ -37,15 +37,17 @@ #include #endif -#include "Global/GlobalDefines.h" -#include "Engine/FitCurve.h" - CLANG_DIAG_OFF(deprecated-declarations) #include #include #include CLANG_DIAG_ON(deprecated-declarations) +#include "Global/GlobalDefines.h" +#include "Engine/FitCurve.h" +#include "Engine/EngineFwd.h" + + #define kRotoLayerBaseName "Layer" #define kRotoBezierBaseName "Bezier" #define kRotoOpenBezierBaseName "Pencil" @@ -61,37 +63,6 @@ CLANG_DIAG_ON(deprecated-declarations) #define kRotoPaintDodgeBaseName "Dodge" #define kRotoPaintBurnBaseName "Burn" -namespace Natron { -class Image; -class ImageComponents; -class Node; -} -namespace boost { namespace serialization { class access; } } - -class RectI; -class RectD; -class KnobI; -class KnobBool; -class KnobDouble; -class KnobInt; -class KnobChoice; -class KnobColor; -typedef struct _cairo_pattern cairo_pattern_t; - -class Curve; -class Bezier; -class RotoItemSerialization; -class BezierCP; - -/** - * @class A base class for all items made by the roto context - **/ -class RotoContext; -class RotoLayer; - -namespace Transform { -struct Matrix3x3; -} struct RotoItemPrivate; class RotoItem diff --git a/Engine/RotoItemSerialization.h b/Engine/RotoItemSerialization.h index 10cfee2521..4b190e9cf3 100644 --- a/Engine/RotoItemSerialization.h +++ b/Engine/RotoItemSerialization.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_OFF GCC_DIAG_OFF(unused-parameter) @@ -44,6 +46,7 @@ GCC_DIAG_ON(unused-parameter) #include "Engine/RotoContext.h" #include "Engine/RotoLayer.h" #include "Engine/RotoContextPrivate.h" +#include "Engine/EngineFwd.h" #define ROTO_ITEM_INTRODUCES_LABEL 2 diff --git a/Engine/RotoLayer.h b/Engine/RotoLayer.h index b58dc164f6..a51b28199d 100644 --- a/Engine/RotoLayer.h +++ b/Engine/RotoLayer.h @@ -37,62 +37,21 @@ #include #endif -#include "Global/GlobalDefines.h" -#include "Engine/FitCurve.h" -#include "Engine/RotoItem.h" - CLANG_DIAG_OFF(deprecated-declarations) #include #include #include CLANG_DIAG_ON(deprecated-declarations) -#define kRotoLayerBaseName "Layer" -#define kRotoBezierBaseName "Bezier" -#define kRotoOpenBezierBaseName "Pencil" -#define kRotoEllipseBaseName "Ellipse" -#define kRotoRectangleBaseName "Rectangle" -#define kRotoPaintBrushBaseName "Brush" -#define kRotoPaintEraserBaseName "Eraser" -#define kRotoPaintBlurBaseName "Blur" -#define kRotoPaintSmearBaseName "Smear" -#define kRotoPaintSharpenBaseName "Sharpen" -#define kRotoPaintCloneBaseName "Clone" -#define kRotoPaintRevealBaseName "Reveal" -#define kRotoPaintDodgeBaseName "Dodge" -#define kRotoPaintBurnBaseName "Burn" - -namespace Natron { -class Image; -class ImageComponents; -class Node; -} -namespace boost { namespace serialization { class access; } } - -class RectI; -class RectD; -class KnobI; -class KnobBool; -class KnobDouble; -class KnobInt; -class KnobChoice; -class KnobColor; -typedef struct _cairo_pattern cairo_pattern_t; - -class Curve; -class Bezier; -class RotoItemSerialization; -class BezierCP; +#include "Global/GlobalDefines.h" +#include "Engine/FitCurve.h" +#include "Engine/RotoItem.h" +#include "Engine/EngineFwd.h" + /** * @class A base class for all items made by the roto context **/ -class RotoContext; -class RotoLayer; - -namespace Transform { -struct Matrix3x3; -} /** * @class A RotoLayer is a group of RotoItem. This allows the context to sort diff --git a/Engine/RotoLayerSerialization.h b/Engine/RotoLayerSerialization.h index 9b9cf9aba3..08476c195a 100644 --- a/Engine/RotoLayerSerialization.h +++ b/Engine/RotoLayerSerialization.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_OFF GCC_DIAG_OFF(unused-parameter) @@ -47,6 +49,8 @@ GCC_DIAG_ON(unused-parameter) #include "Engine/RotoItemSerialization.h" #include "Engine/RotoLayer.h" #include "Engine/RotoStrokeItemSerialization.h" +#include "Engine/EngineFwd.h" + #define ROTO_LAYER_SERIALIZATION_REMOVES_IS_BEZIER 2 #define ROTO_LAYER_SERIALIZATION_VERSION ROTO_LAYER_SERIALIZATION_REMOVES_IS_BEZIER diff --git a/Engine/RotoPaint.h b/Engine/RotoPaint.h index 17d1c6ebf3..e262818be4 100644 --- a/Engine/RotoPaint.h +++ b/Engine/RotoPaint.h @@ -19,7 +19,17 @@ #ifndef ROTOPAINT_H #define ROTOPAINT_H +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + +#include "Global/Macros.h" + #include "Engine/EffectInstance.h" +#include "Engine/EngineFwd.h" + struct RotoPaintPrivate; class RotoPaint : public Natron::EffectInstance diff --git a/Engine/RotoPoint.h b/Engine/RotoPoint.h index 37e9d441a6..3ada3fec01 100644 --- a/Engine/RotoPoint.h +++ b/Engine/RotoPoint.h @@ -37,77 +37,37 @@ #include #endif -#include "Global/GlobalDefines.h" -#include "Engine/FitCurve.h" - CLANG_DIAG_OFF(deprecated-declarations) #include #include #include CLANG_DIAG_ON(deprecated-declarations) -#define kRotoLayerBaseName "Layer" -#define kRotoBezierBaseName "Bezier" -#define kRotoOpenBezierBaseName "Pencil" -#define kRotoEllipseBaseName "Ellipse" -#define kRotoRectangleBaseName "Rectangle" -#define kRotoPaintBrushBaseName "Brush" -#define kRotoPaintEraserBaseName "Eraser" -#define kRotoPaintBlurBaseName "Blur" -#define kRotoPaintSmearBaseName "Smear" -#define kRotoPaintSharpenBaseName "Sharpen" -#define kRotoPaintCloneBaseName "Clone" -#define kRotoPaintRevealBaseName "Reveal" -#define kRotoPaintDodgeBaseName "Dodge" -#define kRotoPaintBurnBaseName "Burn" - -namespace Natron { -class Image; -class ImageComponents; -class Node; -} -namespace boost { namespace serialization { class access; } } - -class RectI; -class RectD; -class KnobI; -class KnobBool; -class KnobDouble; -class KnobInt; -class KnobChoice; -class KnobColor; -typedef struct _cairo_pattern cairo_pattern_t; - -class Curve; -class Bezier; -class RotoItemSerialization; -class BezierCP; - -/** - * @class A base class for all items made by the roto context - **/ -class RotoContext; -class RotoLayer; - -namespace Transform { -struct Matrix3x3; -} - - - -struct RotoPoint +#include "Global/GlobalDefines.h" +#include "Engine/FitCurve.h" +#include "Engine/EngineFwd.h" + + +class RotoPoint { - Natron::Point pos; - double pressure; - double timestamp; - - RotoPoint() : pos(), pressure(0), timestamp(0) {} + Natron::Point _pos; + double _pressure; + double _timestamp; + +public: + RotoPoint() : _pos(), _pressure(0), _timestamp(0) {} RotoPoint(const Natron::Point &pos_, double pressure_, double timestamp_) - : pos(pos_), pressure(pressure_), timestamp(timestamp_) {} + : _pos(pos_), _pressure(pressure_), _timestamp(timestamp_) {} RotoPoint(double x, double y, double pressure_, double timestamp_) - : pressure(pressure_), timestamp(timestamp_) { pos.x = x; pos.y = y; } + : _pressure(pressure_), _timestamp(timestamp_) { _pos.x = x; _pos.y = y; } + + const Natron::Point& pos() const { return _pos; } + + double pressure() const { return _pressure; } + + double timestamp() const { return _timestamp; } }; #endif // Engine_RotoPoint_h diff --git a/Engine/RotoSmear.cpp b/Engine/RotoSmear.cpp index ecd9c36e6c..8d036f45c9 100644 --- a/Engine/RotoSmear.cpp +++ b/Engine/RotoSmear.cpp @@ -111,7 +111,11 @@ RotoSmear::getRegionOfDefinition(U64 hash,double time, const RenderScale & scale RectD maskRod; boost::shared_ptr node = getNode(); - node->getPaintStrokeRoD(time, &maskRod); + try { + node->getPaintStrokeRoD(time, &maskRod); + } catch (...) { + + } if (rod->isNull()) { *rod = maskRod; } else { diff --git a/Engine/RotoSmear.h b/Engine/RotoSmear.h index 4c7292aaeb..e096a99c07 100644 --- a/Engine/RotoSmear.h +++ b/Engine/RotoSmear.h @@ -19,7 +19,17 @@ #ifndef ROTOSMEAR_H #define ROTOSMEAR_H +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + +#include "Global/Macros.h" + #include "Engine/EffectInstance.h" +#include "Engine/EngineFwd.h" + struct RotoSmearPrivate; class RotoSmear : public Natron::EffectInstance diff --git a/Engine/RotoStrokeItem.cpp b/Engine/RotoStrokeItem.cpp index 2225fd08e9..3bba691f35 100644 --- a/Engine/RotoStrokeItem.cpp +++ b/Engine/RotoStrokeItem.cpp @@ -320,8 +320,7 @@ RotoStrokeItem::setStrokeFinished() frameHoldNode->incrementKnobsAge(); } - getContext()->setStrokeBeingPainted(boost::shared_ptr()); - getContext()->getNode()->setWhileCreatingPaintStroke(false); + getContext()->setWhileCreatingPaintStrokeOnMergeNodes(false); getContext()->clearViewersLastRenderedStrokes(); //Might have to do this somewhere else if several viewers are active on the rotopaint node resetNodesThreadSafety(); @@ -381,11 +380,11 @@ RotoStrokeItem::appendPoint(bool newStroke, const RotoPoint& p) qDebug() << "start stroke!"; t = 0.; // set time origin for this curve - _imp->curveT0 = p.timestamp; - } else if (p.timestamp == 0.) { + _imp->curveT0 = p.timestamp(); + } else if (p.timestamp() == 0.) { t = nk; // some systems may not have a proper timestamp use a dummy one } else { - t = p.timestamp - _imp->curveT0; + t = p.timestamp() - _imp->curveT0; } if (nk > 0) { //Clamp timestamps difference to 1e-3 in case Qt delivers its events all at once @@ -452,14 +451,14 @@ RotoStrokeItem::appendPoint(bool newStroke, const RotoPoint& p) { KeyFrame k; k.setTime(t); - k.setValue(p.pos.x); + k.setValue(p.pos().x); addKeyFrameOk = stroke->xCurve->addKeyFrame(k); ki = (addKeyFrameOk ? nk : (nk - 1)); } { KeyFrame k; k.setTime(t); - k.setValue(p.pos.y); + k.setValue(p.pos().y); bool aok = stroke->yCurve->addKeyFrame(k); assert(aok == addKeyFrameOk); if (aok != addKeyFrameOk) { @@ -470,7 +469,7 @@ RotoStrokeItem::appendPoint(bool newStroke, const RotoPoint& p) { KeyFrame k; k.setTime(t); - k.setValue(p.pressure); + k.setValue(p.pressure()); bool aok = stroke->pressureCurve->addKeyFrame(k); assert(aok == addKeyFrameOk); if (aok != addKeyFrameOk) { diff --git a/Engine/RotoStrokeItem.h b/Engine/RotoStrokeItem.h index 2aeb4efb4f..a04964555a 100644 --- a/Engine/RotoStrokeItem.h +++ b/Engine/RotoStrokeItem.h @@ -37,64 +37,21 @@ #include #endif -#include "Global/GlobalDefines.h" -#include "Engine/FitCurve.h" -#include "Engine/RotoDrawableItem.h" - CLANG_DIAG_OFF(deprecated-declarations) #include #include #include CLANG_DIAG_ON(deprecated-declarations) -#define kRotoLayerBaseName "Layer" -#define kRotoBezierBaseName "Bezier" -#define kRotoOpenBezierBaseName "Pencil" -#define kRotoEllipseBaseName "Ellipse" -#define kRotoRectangleBaseName "Rectangle" -#define kRotoPaintBrushBaseName "Brush" -#define kRotoPaintEraserBaseName "Eraser" -#define kRotoPaintBlurBaseName "Blur" -#define kRotoPaintSmearBaseName "Smear" -#define kRotoPaintSharpenBaseName "Sharpen" -#define kRotoPaintCloneBaseName "Clone" -#define kRotoPaintRevealBaseName "Reveal" -#define kRotoPaintDodgeBaseName "Dodge" -#define kRotoPaintBurnBaseName "Burn" - -namespace Natron { -class Image; -class ImageComponents; -class Node; -} -namespace boost { namespace serialization { class access; } } - -class RectI; -class RectD; -class KnobI; -class KnobBool; -class KnobDouble; -class KnobInt; -class KnobChoice; -class KnobColor; -typedef struct _cairo_pattern cairo_pattern_t; +#include "Global/GlobalDefines.h" +#include "Engine/FitCurve.h" +#include "Engine/RotoDrawableItem.h" +#include "Engine/EngineFwd.h" -class Curve; -class Bezier; -struct RotoPoint; -class RotoItemSerialization; -class BezierCP; /** * @class A base class for all items made by the roto context **/ -class RotoContext; -class RotoLayer; - -namespace Transform { -struct Matrix3x3; -} - /** @@ -121,7 +78,7 @@ class RotoStrokeItem : public RotoDrawableItem * @brief Appends to the paint stroke the raw points list. * @returns True if the number of points is > 1 **/ - bool appendPoint(bool newStroke,const RotoPoint& p); + bool appendPoint(bool newStroke, const RotoPoint& p); void addStroke(const boost::shared_ptr& xCurve, const boost::shared_ptr& yCurve, diff --git a/Engine/RotoStrokeItemSerialization.h b/Engine/RotoStrokeItemSerialization.h index 34d9c9421f..00cf5cf5f3 100644 --- a/Engine/RotoStrokeItemSerialization.h +++ b/Engine/RotoStrokeItemSerialization.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_OFF GCC_DIAG_OFF(unused-parameter) @@ -44,13 +46,13 @@ GCC_DIAG_ON(unused-parameter) #include "Engine/RotoContext.h" #include "Engine/RotoLayer.h" #include "Engine/RotoContextPrivate.h" +#include "Engine/EngineFwd.h" + #define ROTO_STROKE_INTRODUCES_MULTIPLE_STROKES 2 #define ROTO_STROKE_SERIALIZATION_VERSION ROTO_STROKE_INTRODUCES_MULTIPLE_STROKES - - struct StrokePoint { double x,y,pressure; diff --git a/Engine/RotoWrapper.h b/Engine/RotoWrapper.h index d21c739829..4bff831f63 100644 --- a/Engine/RotoWrapper.h +++ b/Engine/RotoWrapper.h @@ -26,19 +26,20 @@ // ***** END PYTHON BLOCK ***** #include + +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif #include "Engine/ParameterWrapper.h" +#include "Engine/EngineFwd.h" + -class RotoContext; -class RotoItem; -class Bezier; -class RotoLayer; +class Layer; // defined below -class Layer; class ItemBase { diff --git a/Engine/ScriptObject.h b/Engine/ScriptObject.h index 0e32a04b54..980f302d46 100644 --- a/Engine/ScriptObject.h +++ b/Engine/ScriptObject.h @@ -19,12 +19,23 @@ #ifndef SCRIPTOBJECT_H #define SCRIPTOBJECT_H +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + #include +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif +#include "Engine/EngineFwd.h" + + struct ScriptObjectPrivate; class ScriptObject { diff --git a/Engine/Settings.cpp b/Engine/Settings.cpp index 4e8e1c1921..918d2f2955 100644 --- a/Engine/Settings.cpp +++ b/Engine/Settings.cpp @@ -895,12 +895,14 @@ Settings::initializeKnobsNodeGraph() _nodegraphTab->addKnob(_useInputAForMergeAutoConnect); _usePluginIconsInNodeGraph = Natron::createKnob(this, "Display plug-in icon on node-graph"); + _usePluginIconsInNodeGraph->setName("usePluginIcons"); _usePluginIconsInNodeGraph->setHintToolTip("When checked, each node that has a plug-in icon will display it in the node-graph." "Changing this option will not affect already existing nodes, unless a restart of Natron is made."); _usePluginIconsInNodeGraph->setAnimationEnabled(false); _nodegraphTab->addKnob(_usePluginIconsInNodeGraph); _useAntiAliasing = Natron::createKnob(this, "Anti-Aliasing"); + _useAntiAliasing->setName("antiAliasing"); _useAntiAliasing->setHintToolTip("When checked, the node graph will be painted using anti-aliasing. Unchecking it may increase performances." " Changing this requires a restart of Natron"); _useAntiAliasing->setAnimationEnabled(false); diff --git a/Engine/Settings.h b/Engine/Settings.h index 13d50fbf84..e37e4b1db6 100644 --- a/Engine/Settings.h +++ b/Engine/Settings.h @@ -33,6 +33,8 @@ #include "Global/GlobalDefines.h" #include "Engine/Knob.h" +#include "Engine/EngineFwd.h" + #define kQSettingsSoftwareMajorVersionSettingName "SoftwareVersionMajor" @@ -40,25 +42,6 @@ @todo Move this class to QSettings instead*/ -namespace Natron { -class LibraryBinary; -class Plugin; -} - -class KnobI; -class KnobFile; -class KnobPage; -class KnobDouble; -class KnobInt; -class KnobBool; -class KnobButton; -class KnobGroup; -class KnobChoice; -class KnobPath; -class KnobColor; -class KnobString; -class QSettings; -class KnobSeparator; class Settings : public KnobHolder { diff --git a/Engine/Singleton.h b/Engine/Singleton.h index bdb5a0d4ec..4e42e106b1 100644 --- a/Engine/Singleton.h +++ b/Engine/Singleton.h @@ -26,8 +26,13 @@ // ***** END PYTHON BLOCK ***** #include // for std::atexit() + #include +#include "Global/Macros.h" + +#include "Engine/EngineFwd.h" + // Singleton pattern ( thread-safe) , to have 1 global ptr template diff --git a/Engine/StandardPaths.cpp b/Engine/StandardPaths.cpp index 86561bb88d..2d31b6b248 100644 --- a/Engine/StandardPaths.cpp +++ b/Engine/StandardPaths.cpp @@ -56,8 +56,9 @@ #include #include #include + CLANG_DIAG_OFF(deprecated) -#include +#include #include #include CLANG_DIAG_ON(deprecated) diff --git a/Engine/StandardPaths.h b/Engine/StandardPaths.h index 7d3c72b938..5fddac4f26 100644 --- a/Engine/StandardPaths.h +++ b/Engine/StandardPaths.h @@ -27,6 +27,11 @@ #include +#include "Global/Macros.h" + +#include "Engine/EngineFwd.h" + + namespace Natron { class StandardPaths { diff --git a/Engine/StringAnimationManager.h b/Engine/StringAnimationManager.h index d2f773013d..b4b5131035 100644 --- a/Engine/StringAnimationManager.h +++ b/Engine/StringAnimationManager.h @@ -29,12 +29,15 @@ #include #endif #include + +#include "Global/Macros.h" #include "Global/GlobalDefines.h" -class KnobI; -struct StringAnimationManagerPrivate; +#include "Engine/EngineFwd.h" +struct StringAnimationManagerPrivate; + ///not thread-safe class StringAnimationManager { diff --git a/Engine/TextureRect.h b/Engine/TextureRect.h index 269b89bd76..32e4322957 100644 --- a/Engine/TextureRect.h +++ b/Engine/TextureRect.h @@ -27,7 +27,10 @@ #include // min, max -class RectI; +#include "Global/Macros.h" + +#include "Engine/EngineFwd.h" + /** @class This class describes the rectangle (or portion) of an image that is contained * into a texture. x1,y1,x2,y2 are respectivly the image coordinates of the left,bottom,right,top @@ -35,8 +38,14 @@ class RectI; * and likewise y2 - y1 != h , this is because a texture might not contain all the lines/columns * of the image in the portion defined. **/ -struct TextureRect +class TextureRect { +public: + int x1,y1,x2,y2; // the edges of the texture. These are coordinates in the full size image + int w,h; // the width and height of the texture. This has nothing to do with x,y,r,t + int closestPo2; //< the closest power of 2 of the original region of interest of the image + double par; // the par of the associated image + TextureRect() : x1(0) , y1(0) @@ -92,11 +101,6 @@ struct TextureRect set(0, 0, 0, 0, 0, 0, 1, 1.); } - int x1,y1,x2,y2; // the edges of the texture. These are coordinates in the full size image - int w,h; // the width and height of the texture. This has nothing to do with x,y,r,t - int closestPo2; //< the closest power of 2 of the original region of interest of the image - double par; // the par of the associated image - bool isNull() const { return (x2 <= x1) || (y2 <= y1); diff --git a/Engine/TextureRectSerialization.h b/Engine/TextureRectSerialization.h index ebcde6ee43..0abd6eb145 100644 --- a/Engine/TextureRectSerialization.h +++ b/Engine/TextureRectSerialization.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_OFF GCC_DIAG_OFF(unused-parameter) @@ -36,6 +38,8 @@ GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_ON GCC_DIAG_ON(unused-parameter) #endif #include "Engine/TextureRect.h" +#include "Engine/EngineFwd.h" + #define TEXTURE_RECT_SERIALIZATION_INTRODUCES_PAR 2 #define TEXTURE_RECT_VERSION TEXTURE_RECT_SERIALIZATION_INTRODUCES_PAR diff --git a/Engine/ThreadStorage.h b/Engine/ThreadStorage.h index 53f1435fcd..321b7400c7 100644 --- a/Engine/ThreadStorage.h +++ b/Engine/ThreadStorage.h @@ -25,10 +25,14 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include #include +#include "Engine/EngineFwd.h" + // A class that inherits from QThreadStorage, but never sets local data in the main thread. // It uses an actual instance of the data. // That way, the ThreadStorage class can be destroyed before leaving the main thread. diff --git a/Engine/TimeLine.cpp b/Engine/TimeLine.cpp index d5083b63fa..8e81e681e2 100644 --- a/Engine/TimeLine.cpp +++ b/Engine/TimeLine.cpp @@ -58,9 +58,7 @@ TimeLine::seekFrame(SequenceTime frame, Natron::OutputEffectInstance* caller, Natron::TimelineChangeReasonEnum reason) { - if (reason == Natron::eTimelineChangeReasonUserSeek || - reason == Natron::eTimelineChangeReasonCurveEditorSeek || - reason == Natron::eTimelineChangeReasonDopeSheetEditorSeek) { + if (reason != Natron::eTimelineChangeReasonPlaybackSeek) { Q_EMIT frameAboutToChange(); } bool changed = false; diff --git a/Engine/TimeLine.h b/Engine/TimeLine.h index 6fe290a6a5..9df56e8527 100644 --- a/Engine/TimeLine.h +++ b/Engine/TimeLine.h @@ -26,6 +26,7 @@ // ***** END PYTHON BLOCK ***** #include + #include "Global/Macros.h" CLANG_DIAG_OFF(deprecated) #include @@ -34,17 +35,14 @@ CLANG_DIAG_ON(deprecated) #include "Global/GlobalDefines.h" +#include "Engine/EngineFwd.h" + /** * @brief A simple TimeLine representing the time for image sequences. * The interval [_firstFrame,_lastFrame] represents where images exist in the time space. * The interval [_leftBoundary,_rightBoundary] represents what the user interval of interest within the time space. * The _currentFrame represents the current time in the time space. It doesn't have to be within any aforementioned interval. **/ -namespace Natron { -class Project; -class OutputEffectInstance; -class Node; -} class TimeLine : public QObject diff --git a/Engine/Timer.h b/Engine/Timer.h index 252d8895e1..bcaddae8b6 100644 --- a/Engine/Timer.h +++ b/Engine/Timer.h @@ -31,14 +31,20 @@ // //---------------------------------------------------------------------------- -#include -#include #ifdef _WIN32 - #include +#include #else - #include +#include #endif +#include "Global/Macros.h" + +#include +#include + +#include "Engine/EngineFwd.h" + + #ifdef _WIN32 int gettimeofday (struct timeval *tv, void *tz); #endif @@ -49,7 +55,6 @@ enum PlayStateEnum ePlayStatePause, }; -class QMutex; class Timer : public QObject { diff --git a/Engine/Transform.cpp b/Engine/Transform.cpp index 63ae1ca33e..7d32bb5ec7 100644 --- a/Engine/Transform.cpp +++ b/Engine/Transform.cpp @@ -162,7 +162,16 @@ Matrix3x3::Matrix3x3(const Matrix3x3 & mat) Matrix3x3 & Matrix3x3::operator=(const Matrix3x3 & m) { - a = m.a; b = m.b; c = m.c; d = m.d; e = m.e; f = m.f; g = m.g; h = m.h; i = m.i; return *this; + a = m.a; + b = m.b; + c = m.c; + d = m.d; + e = m.e; + f = m.f; + g = m.g; + h = m.h; + i = m.i; + return *this; } bool diff --git a/Engine/Transform.h b/Engine/Transform.h index aba0278344..543fe55b97 100644 --- a/Engine/Transform.h +++ b/Engine/Transform.h @@ -27,7 +27,10 @@ #include -class RectD; +#include "Global/Macros.h" + +#include "Engine/EngineFwd.h" + #ifndef M_PI #define M_PI 3.14159265358979323846264338327950288 /* pi */ diff --git a/Engine/Variant.h b/Engine/Variant.h index be60d35ce8..636d329af8 100644 --- a/Engine/Variant.h +++ b/Engine/Variant.h @@ -36,7 +36,8 @@ CLANG_DIAG_ON(deprecated) #include #include -#include "Global/Macros.h" +#include "Engine/EngineFwd.h" + class Variant : public QVariant diff --git a/Engine/VariantSerialization.h b/Engine/VariantSerialization.h index 29898add3b..8352e9402f 100644 --- a/Engine/VariantSerialization.h +++ b/Engine/VariantSerialization.h @@ -29,6 +29,8 @@ #include +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_OFF GCC_DIAG_OFF(unused-parameter) @@ -41,6 +43,9 @@ GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_ON GCC_DIAG_ON(unused-parameter) #endif +#include "Engine/EngineFwd.h" + + template void Variant::save(Archive & ar, diff --git a/Engine/ViewerInstance.cpp b/Engine/ViewerInstance.cpp index 6d1273f993..426bccd805 100644 --- a/Engine/ViewerInstance.cpp +++ b/Engine/ViewerInstance.cpp @@ -348,7 +348,7 @@ static void updateLastStrokeDataRecursively(Natron::Node* node,const NodePtr& ro if (invalidate) { node->invalidateLastPaintStrokeDataNoRotopaint(); } else { - node->setLastPaintStrokeDataNoRotopaint(lastStrokeBbox); + node->setLastPaintStrokeDataNoRotopaint(); } if (node == rotoPaintNode.get()) { @@ -372,8 +372,7 @@ class ViewerParallelRenderArgsSetter : public ParallelRenderArgsSetter NodePtr viewerInputNode; public: - ViewerParallelRenderArgsSetter(NodeCollection* n, - double time, + ViewerParallelRenderArgsSetter(double time, int view, bool isRenderUserInteraction, bool isSequential, @@ -389,7 +388,7 @@ class ViewerParallelRenderArgsSetter : public ParallelRenderArgsSetter bool draftMode, bool viewerProgressReportEnabled, const boost::shared_ptr& stats) - : ParallelRenderArgsSetter(n,time,view,isRenderUserInteraction,isSequential,canAbort,renderAge,treeRoot, request,textureIndex,timeline,rotoPaintNode, isAnalysis, draftMode, viewerProgressReportEnabled,stats) + : ParallelRenderArgsSetter(time,view,isRenderUserInteraction,isSequential,canAbort,renderAge,treeRoot, request,textureIndex,timeline,rotoPaintNode, isAnalysis, draftMode, viewerProgressReportEnabled,stats) , rotoNode(rotoPaintNode) , viewerNode(treeRoot) , viewerInputNode() @@ -440,6 +439,7 @@ ViewerInstance::getViewerArgsAndRenderViewer(SequenceTime time, int view, U64 viewerHash, const boost::shared_ptr& rotoPaintNode, + const boost::shared_ptr& activeStroke, const boost::shared_ptr& stats, boost::shared_ptr* argsA, boost::shared_ptr* argsB) @@ -456,14 +456,6 @@ ViewerInstance::getViewerArgsAndRenderViewer(SequenceTime time, eStatusFailed, eStatusFailed }; - boost::shared_ptr activeStroke; - if (rotoPaintNode) { - activeStroke = rotoPaintNode->getRotoContext()->getStrokeBeingPainted(); - if (!activeStroke) { - return eStatusReplyDefault; - } - } - NodePtr thisNode = getNode(); @@ -492,8 +484,7 @@ ViewerInstance::getViewerArgsAndRenderViewer(SequenceTime time, - ViewerParallelRenderArgsSetter tls(getApp()->getProject().get(), - time, + ViewerParallelRenderArgsSetter tls(time, view, true, false, @@ -526,14 +517,14 @@ ViewerInstance::getViewerArgsAndRenderViewer(SequenceTime time, RectD lastStrokeBbox; int lastAge,newAge; NodePtr mergeNode = activeStroke->getMergeNode(); - lastAge = mergeNode->getStrokeImageAge(); + lastAge = getApp()->getStrokeLastIndex(); int strokeIndex; if (activeStroke->getMostRecentStrokeChangesSinceAge(time, lastAge, &lastStrokePoints, &lastStrokeBbox, &wholeStrokeRod ,&newAge,&strokeIndex)) { + getApp()->updateLastPaintStrokeData(newAge, lastStrokePoints, lastStrokeBbox, strokeIndex); for (NodeList::iterator it = rotoPaintNodes.begin(); it!=rotoPaintNodes.end(); ++it) { - if ((*it)->getAttachedRotoItem() == activeStroke) { - (*it)->updateLastPaintStrokeData(newAge, lastStrokePoints, lastStrokeBbox,strokeIndex); - } + (*it)->prepareForNextPaintStrokeRender(); + } updateLastStrokeDataRecursively(thisNode.get(), rotoPaintNode, lastStrokeBbox, false); } else { @@ -591,7 +582,6 @@ ViewerInstance::renderViewer(int view, if ( (i == 1) && (_imp->uiContext->getCompositingOperator() == Natron::eViewerCompositingOperatorNone) ) { break; } - if (args[i] && args[i]->params) { assert(args[i]->params->textureIndex == i); @@ -841,8 +831,7 @@ ViewerInstance::getRenderViewerArgsAndCheckCache(SequenceTime time, ///need to set TLS for getROD() boost::shared_ptr frameArgs; if (useTLS) { - frameArgs.reset(new ParallelRenderArgsSetter(getApp()->getProject().get(), - time, + frameArgs.reset(new ParallelRenderArgsSetter(time, view, !isSequential, // is this render due to user interaction ? isSequential, // is this sequential ? @@ -925,7 +914,6 @@ ViewerInstance::getRenderViewerArgsAndCheckCache(SequenceTime time, outArgs->params->renderAge = renderAge; outArgs->params->setUniqueID(textureIndex); outArgs->params->srcPremult = outArgs->activeInputToRender->getOutputPremultiplication(); - ///Texture rect contains the pixel coordinates in the image to be rendered outArgs->params->textureRect.x1 = roi.x1; outArgs->params->textureRect.x2 = roi.x2; @@ -1164,8 +1152,7 @@ ViewerInstance::renderViewer_internal(int view, return stat; } - frameArgs.reset(new ViewerParallelRenderArgsSetter(getApp()->getProject().get(), - inArgs.params->time, + frameArgs.reset(new ViewerParallelRenderArgsSetter(inArgs.params->time, view, !isSequentialRender, isSequentialRender, @@ -1200,8 +1187,7 @@ ViewerInstance::renderViewer_internal(int view, if (_imp->lastRotoPaintTickParams[inArgs.params->textureIndex] && inArgs.params->mipMapLevel == _imp->lastRotoPaintTickParams[inArgs.params->textureIndex]->mipMapLevel && inArgs.params->textureRect.contains(_imp->lastRotoPaintTickParams[inArgs.params->textureIndex]->textureRect)) { //Overwrite the RoI to only the last portion rendered - RectD lastPaintBbox; - getNode()->getLastPaintStrokeRoD(&lastPaintBbox); + RectD lastPaintBbox = getApp()->getLastPaintStrokeBbox(); const double par = inArgs.activeInputToRender->getPreferredAspectRatio(); lastPaintBbox.toPixelEnclosing(inArgs.params->mipMapLevel, par, &lastPaintBboxPixel); @@ -2648,7 +2634,12 @@ ViewerInstance::ViewerInstancePrivate::updateViewer(boost::shared_ptrupdateOnlyRoi); updateViewerPboIndex = (updateViewerPboIndex + 1) % 2; - if (!instance->getApp()->getIsUserPainting().get()) { + boost::shared_ptr rotoPaintNode; + boost::shared_ptr curStroke; + bool isDrawing; + instance->getApp()->getActiveRotoDrawingStroke(&rotoPaintNode, &curStroke,&isDrawing); + + if (!isDrawing) { uiContext->updateColorPicker(params->textureIndex); } } diff --git a/Engine/ViewerInstance.h b/Engine/ViewerInstance.h index afb76e2c0a..ae750b1e86 100644 --- a/Engine/ViewerInstance.h +++ b/Engine/ViewerInstance.h @@ -28,23 +28,11 @@ #include #include "Global/Macros.h" + #include "Engine/OutputEffectInstance.h" +#include "Engine/EngineFwd.h" -class ParallelRenderArgsSetter; -class RenderingFlagSetter; -struct RequestedFrame; -namespace Natron { -class Image; -class FrameEntry; -class EffectInstance; -namespace Color { -class Lut; -} -} -class UpdateViewerParams; -class TimeLine; -class OpenGLViewerI; -struct TextureRect; +class UpdateViewerParams; // ViewerInstancePrivate typedef std::map,NodeRenderStats > RenderStatsMap; @@ -147,6 +135,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON int view, U64 viewerHash, const boost::shared_ptr& rotoPaintNode, + const boost::shared_ptr& strokeItem, const boost::shared_ptr& stats, boost::shared_ptr* argsA, boost::shared_ptr* argsB); diff --git a/Engine/ViewerInstancePrivate.h b/Engine/ViewerInstancePrivate.h index bb8019b6ec..be966484e1 100644 --- a/Engine/ViewerInstancePrivate.h +++ b/Engine/ViewerInstancePrivate.h @@ -45,15 +45,10 @@ #include "Engine/Settings.h" #include "Engine/Image.h" #include "Engine/TextureRect.h" +#include "Engine/EngineFwd.h" #define GAMMA_LUT_NB_VALUES 1023 -namespace Natron { -class FrameEntry; -class FrameParams; -} - - struct OnGoingRenderInfo { diff --git a/Global/Enums.h b/Global/Enums.h index c1989a751c..4b253be97d 100644 --- a/Global/Enums.h +++ b/Global/Enums.h @@ -48,6 +48,7 @@ enum TimelineChangeReasonEnum eTimelineChangeReasonPlaybackSeek = 1, eTimelineChangeReasonCurveEditorSeek = 2, eTimelineChangeReasonDopeSheetEditorSeek = 3, + eTimelineChangeReasonOtherSeek }; enum StatusEnum diff --git a/Gui/AboutWindow.h b/Gui/AboutWindow.h index 4c73a0f187..eb869889a7 100644 --- a/Gui/AboutWindow.h +++ b/Gui/AboutWindow.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef ABOUTWINDOW_H #define ABOUTWINDOW_H @@ -34,19 +33,8 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -class QTextBrowser; -class QTabWidget; -class QVBoxLayout; -class QHBoxLayout; -class Button; -class Gui; -class TableModel; -class TableView; -class QItemSelection; +#include "Gui/GuiFwd.h" -namespace Natron { - class Label; -} class AboutWindow : public QDialog diff --git a/Gui/ActionShortcuts.h b/Gui/ActionShortcuts.h index 2fc41d03e3..76e114ecdc 100644 --- a/Gui/ActionShortcuts.h +++ b/Gui/ActionShortcuts.h @@ -29,11 +29,12 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include #include -#include "Global/Macros.h" CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -43,6 +44,8 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) +#include "Gui/GuiFwd.h" + #define kShortcutGroupGlobal "Global" #define kShortcutGroupNodegraph "NodeGraph" #define kShortcutGroupCurveEditor "CurveEditor" @@ -556,7 +559,7 @@ CLANG_DIAG_ON(uninitialized) #define kShortcutDescActionCurveEditorHorizontal "Horizontal Interpolation" #define kShortcutIDActionCurveEditorBreak "break" -#define kShortcutDescActionCurveEditorBreak "Break Curvature" +#define kShortcutDescActionCurveEditorBreak "Break" #define kShortcutIDActionCurveEditorSelectAll "selectAll" #define kShortcutDescActionCurveEditorSelectAll "Select All Keyframes" @@ -608,7 +611,6 @@ CLANG_DIAG_ON(uninitialized) #define kShortcutIDActionScriptShowOutput "showHideOutput" #define kShortcutDescActionScriptShowOutput "Show/Hide Output Window" -class QWidget; inline QKeySequence diff --git a/Gui/AddKnobDialog.cpp b/Gui/AddKnobDialog.cpp index 498aed59da..64081a4960 100644 --- a/Gui/AddKnobDialog.cpp +++ b/Gui/AddKnobDialog.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include @@ -37,6 +37,7 @@ #include "Engine/KnobSerialization.h" #include "Engine/KnobTypes.h" #include "Engine/Node.h" +#include "Engine/NodeGroup.h" #include "Gui/ActionShortcuts.h" #include "Gui/ComboBox.h" @@ -57,7 +58,7 @@ struct AddKnobDialogPrivate { boost::shared_ptr knob; boost::shared_ptr originalKnobSerialization; - bool isKnobAlias; + boost::shared_ptr isKnobAlias; DockablePanel* panel; @@ -144,12 +145,12 @@ struct AddKnobDialogPrivate ComboBox* parentPage; std::list userGroups; - std::list userPages; //< all user pages except the "User" one + std::list > userPages; //< all user pages except the "User" one AddKnobDialogPrivate(DockablePanel* panel) : knob() , originalKnobSerialization() - , isKnobAlias(false) + , isKnobAlias() , panel(panel) , vLayout(0) , mainContainer(0) @@ -206,6 +207,7 @@ struct AddKnobDialogPrivate { } + void setVisibleLabel(bool visible); void setVisibleMinMax(bool visible); @@ -238,9 +240,114 @@ struct AddKnobDialogPrivate void createKnobFromSelection(int type,int optionalGroupIndex = -1); KnobGroup* getSelectedGroup() const; + + template + void setKnobMinMax(KnobI* knob); + + boost::shared_ptr getSelectedPage() const; }; -static int getChoiceIndexFromKnobType(KnobI* knob) +enum ParamDataTypeEnum { + eParamDataTypeInteger, // 0 + eParamDataTypeInteger2D, // 1 + eParamDataTypeInteger3D, // 2 + eParamDataTypeFloatingPoint, //3 + eParamDataTypeFloatingPoint2D, // 4 + eParamDataTypeFloatingPoint3D, // 5 + eParamDataTypeColorRGB, // 6 + eParamDataTypeColorRGBA, // 7 + eParamDataTypeChoice, // 8 + eParamDataTypeCheckbox, // 9 + eParamDataTypeLabel, // 10 + eParamDataTypeTextInput, // 11 + eParamDataTypeInputFile, // 12 + eParamDataTypeOutputFile, // 13 + eParamDataTypeDirectory, // 14 + eParamDataTypeGroup, // 15 + eParamDataTypePage, // 16 + eParamDataTypeButton, // 17 + eParamDataTypeCount // 18 +}; + +static const char* dataTypeString(ParamDataTypeEnum t) +{ + switch (t) { + case eParamDataTypeInteger: + return "Integer"; + case eParamDataTypeInteger2D: + return "Integer 2D"; + case eParamDataTypeInteger3D: + return "Integer 3D"; + case eParamDataTypeFloatingPoint: + return "Floating Point"; + case eParamDataTypeFloatingPoint2D: + return "Floating Point 2D"; + case eParamDataTypeFloatingPoint3D: + return "Floating Point 3D"; + case eParamDataTypeColorRGB: + return "Color RGB"; + case eParamDataTypeColorRGBA: + return "Color RGBA"; + case eParamDataTypeChoice: + return "Choice (Pulldown)"; + case eParamDataTypeCheckbox: + return "Checkbox"; + case eParamDataTypeLabel: + return "Label"; + case eParamDataTypeTextInput: + return "Text Input"; + case eParamDataTypeInputFile: + return "Input File"; + case eParamDataTypeOutputFile: + return "Output File"; + case eParamDataTypeDirectory: + return "Directory"; + case eParamDataTypeGroup: + return "Group"; + case eParamDataTypePage: + return "Page"; + case eParamDataTypeButton: + return "Button"; + default: + return NULL; + } +} + +static int dataTypeDim(ParamDataTypeEnum t) +{ + switch (t) { + case eParamDataTypeInteger: + return 1; + case eParamDataTypeInteger2D: + return 2; + case eParamDataTypeInteger3D: + return 3; + case eParamDataTypeFloatingPoint: + return 1; + case eParamDataTypeFloatingPoint2D: + return 2; + case eParamDataTypeFloatingPoint3D: + return 3; + case eParamDataTypeColorRGB: + return 3; + case eParamDataTypeColorRGBA: + return 4; + case eParamDataTypeChoice: + case eParamDataTypeCheckbox: + case eParamDataTypeLabel: + case eParamDataTypeTextInput: + case eParamDataTypeInputFile: + case eParamDataTypeOutputFile: + case eParamDataTypeDirectory: + case eParamDataTypeGroup: + case eParamDataTypePage: + case eParamDataTypeButton: + default: + return 1; + } +} + +static ParamDataTypeEnum getChoiceIndexFromKnobType(KnobI* knob) { int dim = knob->getDimension(); @@ -260,60 +367,83 @@ static int getChoiceIndexFromKnobType(KnobI* knob) if (isInt) { if (dim == 1) { - return 0; + return eParamDataTypeInteger; } else if (dim == 2) { - return 1; + return eParamDataTypeInteger2D; } else if (dim == 3) { - return 2; + return eParamDataTypeInteger3D; } } else if (isDbl) { if (dim == 1) { - return 3; + return eParamDataTypeFloatingPoint; } else if (dim == 2) { - return 4; + return eParamDataTypeFloatingPoint2D; } else if (dim == 3) { - return 5; + return eParamDataTypeFloatingPoint3D; } } else if (isColor) { if (dim == 3) { - return 6; + return eParamDataTypeColorRGB; } else if (dim == 4) { - return 7; + return eParamDataTypeColorRGBA; } } else if (isChoice) { - return 8; + return eParamDataTypeChoice; } else if (isBool) { - return 9; + return eParamDataTypeCheckbox; } else if (isStr) { if (isStr->isLabel()) { - return 10; + return eParamDataTypeLabel; } else { - return 11; + return eParamDataTypeTextInput; } } else if (isFile) { - return 12; + return eParamDataTypeInputFile; } else if (isOutputFile) { - return 13; + return eParamDataTypeOutputFile; } else if (isPath) { - return 14; + return eParamDataTypeDirectory; } else if (isGrp) { - return 15; + return eParamDataTypeGroup; } else if (isPage) { - return 16; + return eParamDataTypePage; } else if (isBtn) { - return 17; + return eParamDataTypeButton; } - return -1; + return eParamDataTypeCount; } -AddKnobDialog::AddKnobDialog(DockablePanel* panel,const boost::shared_ptr& knob,QWidget* parent) +AddKnobDialog::AddKnobDialog(DockablePanel* panel, + const boost::shared_ptr& knob, + QWidget* parent) : QDialog(parent) , _imp(new AddKnobDialogPrivate(panel)) { _imp->knob = knob; assert(!knob || knob->isUserKnob()); - + + { + Natron::EffectInstance* effect = dynamic_cast(panel->getHolder()); + QString title = "Add Parameter"; + if (!knob) { + // Add... + if (effect) { + title += " to "; + title += effect->getScriptName().c_str(); + } + } else { + // Edit... + title = "Edit Parameter "; + if (effect) { + title += effect->getScriptName().c_str(); + title += '.'; + } + title += knob->getName().c_str(); + } + setWindowTitle(title); + } + //QFont font(NATRON_FONT,NATRON_FONT_SIZE_11); _imp->vLayout = new QVBoxLayout(this); @@ -330,17 +460,19 @@ AddKnobDialog::AddKnobDialog(DockablePanel* panel,const boost::shared_ptr { boost::shared_ptr isAlias; + boost::shared_ptr listener; if (knob) { std::list > listeners; knob->getListeners(listeners); if (!listeners.empty()) { - isAlias = listeners.front()->getAliasMaster(); + listener = listeners.front(); + isAlias = listener->getAliasMaster(); if (isAlias != knob) { - isAlias.reset(); + listener.reset(); } } } - _imp->isKnobAlias = isAlias.get() != 0; + _imp->isKnobAlias = listener; } @@ -420,7 +552,8 @@ AddKnobDialog::AddKnobDialog(DockablePanel* panel,const boost::shared_ptr _imp->mainLayout->addRow(_imp->labelLabel, secondRowContainer); } - + + { QWidget* thirdRowContainer = new QWidget(this); QHBoxLayout* thirdRowLayout = new QHBoxLayout(thirdRowContainer); @@ -430,24 +563,10 @@ AddKnobDialog::AddKnobDialog(DockablePanel* panel,const boost::shared_ptr _imp->typeLabel = new Natron::Label(tr("Type:"),thirdRowContainer); _imp->typeChoice = new ComboBox(thirdRowContainer); _imp->typeChoice->setToolTip(Natron::convertFromPlainText(tr("The data type of the parameter."), Qt::WhiteSpaceNormal)); - _imp->typeChoice->addItem("Integer"); - _imp->typeChoice->addItem("Integer 2D"); - _imp->typeChoice->addItem("Integer 3D"); - _imp->typeChoice->addItem("Floating point"); - _imp->typeChoice->addItem("Floating point 2D"); - _imp->typeChoice->addItem("Floating point 3D"); - _imp->typeChoice->addItem("Color RGB"); - _imp->typeChoice->addItem("Color RGBA"); - _imp->typeChoice->addItem("Choice (Pulldown)"); - _imp->typeChoice->addItem("Checkbox"); - _imp->typeChoice->addItem("Label"); - _imp->typeChoice->addItem("Text input"); - _imp->typeChoice->addItem("Input file"); - _imp->typeChoice->addItem("Output file"); - _imp->typeChoice->addItem("Directory"); - _imp->typeChoice->addItem("Group"); - _imp->typeChoice->addItem("Page"); - _imp->typeChoice->addItem("Button"); + for (int i = 0; i < (int)eParamDataTypeCount; ++i) { + assert(_imp->typeChoice->count() == i); + _imp->typeChoice->addItem(tr(dataTypeString((ParamDataTypeEnum)i))); + } QObject::connect(_imp->typeChoice, SIGNAL(currentIndexChanged(int)),this, SLOT(onTypeCurrentIndexChanged(int))); thirdRowLayout->addWidget(_imp->typeChoice); @@ -741,8 +860,11 @@ AddKnobDialog::AddKnobDialog(DockablePanel* panel,const boost::shared_ptr Knob* isInt = dynamic_cast*>(knob.get()); KnobBool* isBool = dynamic_cast(knob.get()); Knob* isStr = dynamic_cast*>(knob.get()); + KnobChoice* isChoice = dynamic_cast(knob.get()); - if (isDbl) { + if (isChoice) { + _imp->defaultStr->setText(isChoice->getEntry(isChoice->getDefaultValue(0)).c_str()); + } else if (isDbl) { _imp->default0->setValue(isDbl->getDefaultValue(0)); if (isDbl->getDimension() >= 2) { _imp->default1->setValue(isDbl->getDefaultValue(1)); @@ -774,6 +896,9 @@ AddKnobDialog::AddKnobDialog(DockablePanel* panel,const boost::shared_ptr const std::map,KnobGui*>& knobs = _imp->panel->getKnobs(); for (std::map,KnobGui*>::const_iterator it = knobs.begin(); it != knobs.end(); ++it) { boost::shared_ptr knob = it->first.lock(); + if (!knob) { + continue; + } if (knob->isUserKnob()) { KnobGroup* isGrp = dynamic_cast(knob.get()); if (isGrp) { @@ -798,90 +923,95 @@ AddKnobDialog::AddKnobDialog(DockablePanel* panel,const boost::shared_ptr _imp->mainLayout->addRow(_imp->parentGroupLabel, optContainer); } - if (!knob) { - QWidget* optContainer = new QWidget(this); - QHBoxLayout* optLayout = new QHBoxLayout(optContainer); - optLayout->setContentsMargins(0, 0, 15, 0); - _imp->parentPageLabel = new Natron::Label(tr("Page:"),optContainer); - _imp->parentPage = new ComboBox(optContainer); - _imp->parentPage->addItem(NATRON_USER_MANAGED_KNOBS_PAGE); - QObject::connect(_imp->parentPage,SIGNAL(currentIndexChanged(int)),this,SLOT(onPageCurrentIndexChanged(int))); - const std::vector >& knobs = _imp->panel->getHolder()->getKnobs(); - for (std::vector >::const_iterator it = knobs.begin() ; it != knobs.end(); ++it) { - if ((*it)->isUserKnob()) { - KnobPage* isPage = dynamic_cast(it->get()); - if (isPage && isPage->getName() != NATRON_USER_MANAGED_KNOBS_PAGE) { - _imp->userPages.push_back(isPage); - } + QWidget* optContainer = new QWidget(this); + QHBoxLayout* optLayout = new QHBoxLayout(optContainer); + optLayout->setContentsMargins(0, 0, 15, 0); + _imp->parentPageLabel = new Natron::Label(tr("Page:"),optContainer); + _imp->parentPage = new ComboBox(optContainer); + _imp->parentPage->addItem(NATRON_USER_MANAGED_KNOBS_PAGE); + QObject::connect(_imp->parentPage,SIGNAL(currentIndexChanged(int)),this,SLOT(onPageCurrentIndexChanged(int))); + const std::vector >& internalKnobs = _imp->panel->getHolder()->getKnobs(); + for (std::vector >::const_iterator it = internalKnobs.begin() ; it != internalKnobs.end(); ++it) { + if ((*it)->isUserKnob()) { + boost::shared_ptr isPage = boost::dynamic_pointer_cast(*it); + if (isPage && isPage->getName() != NATRON_USER_MANAGED_KNOBS_PAGE) { + _imp->userPages.push_back(isPage); } } - - for (std::list::iterator it = _imp->userPages.begin(); it != _imp->userPages.end(); ++it) { - _imp->parentPage->addItem((*it)->getName().c_str()); - } - _imp->parentPage->setToolTip(Natron::convertFromPlainText(tr("The tab under which this parameter will appear."), Qt::WhiteSpaceNormal)); - optLayout->addWidget(_imp->parentPage); - if (knob) { - ////find in which page the knob should be - KnobPage* isTopLevelParentAPage = knob->getTopLevelPage(); - assert(isTopLevelParentAPage); - if (isTopLevelParentAPage->getName() != NATRON_USER_MANAGED_KNOBS_PAGE) { - int index = 1; // 1 because of the "User" item - bool found = false; - for (std::list::iterator it = _imp->userPages.begin(); it != _imp->userPages.end(); ++it, ++index) { - if ((*it) == isTopLevelParentAPage) { - found = true; - break; - } - } - if (found) { - _imp->parentPage->setCurrentIndex(index); + } + + for (std::list >::iterator it = _imp->userPages.begin(); it != _imp->userPages.end(); ++it) { + _imp->parentPage->addItem((*it)->getName().c_str()); + } + _imp->parentPage->setToolTip(Natron::convertFromPlainText(tr("The tab under which this parameter will appear."), Qt::WhiteSpaceNormal)); + optLayout->addWidget(_imp->parentPage); + + bool pageIndexLoaded = false; + if (knob) { + ////find in which page the knob should be + KnobPage* isTopLevelParentAPage = knob->getTopLevelPage(); + assert(isTopLevelParentAPage); + if (isTopLevelParentAPage->getName() != NATRON_USER_MANAGED_KNOBS_PAGE) { + int index = 1; // 1 because of the "User" item + bool found = false; + for (std::list >::iterator it = _imp->userPages.begin(); it != _imp->userPages.end(); ++it, ++index) { + if (it->get() == isTopLevelParentAPage) { + found = true; + break; } } - - + if (found) { + _imp->parentPage->setCurrentIndex(index); + pageIndexLoaded = true; + } } - _imp->mainLayout->addRow(_imp->parentPageLabel, optContainer); - onPageCurrentIndexChanged(0); - } else { // if(!knob) - if (_imp->parentGroup) { - KnobPage* topLvlPage = knob->getTopLevelPage(); - assert(topLvlPage); - boost::shared_ptr parent = knob->getParentKnob(); - KnobGroup* isParentGrp = dynamic_cast(parent.get()); - _imp->parentGroup->addItem("-"); - int idx = 1; - for (std::list::iterator it = _imp->userGroups.begin(); it != _imp->userGroups.end(); ++it, ++idx) { + } + + _imp->mainLayout->addRow(_imp->parentPageLabel, optContainer); + if (!pageIndexLoaded) { + onPageCurrentIndexChanged(0); + } + if (_imp->parentGroup && knob) { + KnobPage* topLvlPage = knob->getTopLevelPage(); + assert(topLvlPage); + boost::shared_ptr parent = knob->getParentKnob(); + KnobGroup* isParentGrp = dynamic_cast(parent.get()); + if (isParentGrp) { + for (std::list::iterator it = _imp->userGroups.begin(); it != _imp->userGroups.end(); ++it) { KnobPage* page = (*it)->getTopLevelPage(); assert(page); ///add only grps whose parent page is the selected page - if (page == topLvlPage) { - _imp->parentGroup->addItem((*it)->getName().c_str()); - if (isParentGrp && isParentGrp == *it) { - _imp->parentGroup->setCurrentIndex(idx); + if (isParentGrp == *it && page == topLvlPage) { + for (int i = 0; i < _imp->parentGroup->count(); ++i) { + if (_imp->parentGroup->itemText(i) == QString(isParentGrp->getName().c_str())) { + _imp->parentGroup->setCurrentIndex(i); + break; + } } + break; } } } } + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::StandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel),Qt::Horizontal,this); QObject::connect(buttons,SIGNAL(rejected()), this, SLOT(reject())); QObject::connect(buttons,SIGNAL(accepted()), this, SLOT(onOkClicked())); _imp->vLayout->addWidget(buttons); - int type; + ParamDataTypeEnum t; if (!knob) { - type = _imp->typeChoice->activeIndex(); + t = (ParamDataTypeEnum)_imp->typeChoice->activeIndex(); } else { - type = getChoiceIndexFromKnobType(knob.get()); - assert(type != -1); + t = getChoiceIndexFromKnobType(knob.get()); + assert(t != eParamDataTypeCount); } - onTypeCurrentIndexChanged(type); + onTypeCurrentIndexChanged((int)t); _imp->panel->setUserPageActiveIndex(); if (knob) { @@ -904,9 +1034,9 @@ AddKnobDialog::onPageCurrentIndexChanged(int index) if (selectedPage == NATRON_USER_MANAGED_KNOBS_PAGE) { parentPage = _imp->panel->getUserPageKnob().get(); } else { - for (std::list::iterator it = _imp->userPages.begin(); it != _imp->userPages.end(); ++it) { + for (std::list >::iterator it = _imp->userPages.begin(); it != _imp->userPages.end(); ++it) { if ((*it)->getName() == selectedPage) { - parentPage = *it; + parentPage = it->get(); break; } } @@ -927,32 +1057,14 @@ AddKnobDialog::onPageCurrentIndexChanged(int index) void AddKnobDialog::onTypeCurrentIndexChanged(int index) { - if (_imp->isKnobAlias) { - _imp->setVisibleAnimates(false); - _imp->setVisibleEvaluate(false); - _imp->setVisibleHide(false); - _imp->setVisibleMenuItems(false); - _imp->setVisibleMinMax(false); - _imp->setVisibleStartNewLine(false); - _imp->setVisibleMultiLine(false); - _imp->setVisibleMultiPath(false); - _imp->setVisibleRichText(false); - _imp->setVisibleSequence(false); - _imp->setVisibleGrpAsTab(false); - _imp->setVisibleParent(false); - _imp->setVisibleDefaultValues(false,AddKnobDialogPrivate::eDefaultValueTypeInt, 1); - return; - } - _imp->setVisiblePage(index != 16); - switch (index) { - case 0: // int - case 1: // int 2D - case 2: // int 3D - case 3: // fp - case 4: // fp 2D - case 5: // fp 3D - case 6: // RGB - case 7: // RGBA + enum ParamDataTypeEnum t = (ParamDataTypeEnum)index; + _imp->setVisiblePage(t != eParamDataTypePage); + _imp->setVisibleLabel(t != eParamDataTypeLabel); + int d = dataTypeDim(t); + switch (t) { + case eParamDataTypeInteger: // int + case eParamDataTypeInteger2D: // int 2D + case eParamDataTypeInteger3D: // int 3D _imp->setVisibleAnimates(true); _imp->setVisibleEvaluate(true); _imp->setVisibleHide(true); @@ -965,23 +1077,30 @@ AddKnobDialog::onTypeCurrentIndexChanged(int index) _imp->setVisibleSequence(false); _imp->setVisibleGrpAsTab(false); _imp->setVisibleParent(true); - if (index == 0 || index == 3) { - _imp->setVisibleDefaultValues(true, - index == 0 ? AddKnobDialogPrivate::eDefaultValueTypeInt : AddKnobDialogPrivate::eDefaultValueTypeDouble, - 1); - } else if (index == 1 || index == 4) { - _imp->setVisibleDefaultValues(true, - index == 1 ? AddKnobDialogPrivate::eDefaultValueTypeInt : AddKnobDialogPrivate::eDefaultValueTypeDouble, - 2); - } else if (index == 2 || index == 5 || index == 6) { - _imp->setVisibleDefaultValues(true, - index == 2 ? AddKnobDialogPrivate::eDefaultValueTypeInt : AddKnobDialogPrivate::eDefaultValueTypeDouble, - 3); - } else if (index == 7) { - _imp->setVisibleDefaultValues(true,AddKnobDialogPrivate::eDefaultValueTypeDouble,4); - } + _imp->setVisibleDefaultValues(true, AddKnobDialogPrivate::eDefaultValueTypeInt, d); break; - case 8: // choice + + case eParamDataTypeFloatingPoint: // fp + case eParamDataTypeFloatingPoint2D: // fp 2D + case eParamDataTypeFloatingPoint3D: // fp 3D + case eParamDataTypeColorRGB: // RGB + case eParamDataTypeColorRGBA: // RGBA + _imp->setVisibleAnimates(true); + _imp->setVisibleEvaluate(true); + _imp->setVisibleHide(true); + _imp->setVisibleMenuItems(false); + _imp->setVisibleMinMax(true); + _imp->setVisibleStartNewLine(true); + _imp->setVisibleMultiLine(false); + _imp->setVisibleMultiPath(false); + _imp->setVisibleRichText(false); + _imp->setVisibleSequence(false); + _imp->setVisibleGrpAsTab(false); + _imp->setVisibleParent(true); + _imp->setVisibleDefaultValues(true, AddKnobDialogPrivate::eDefaultValueTypeDouble, d); + break; + + case eParamDataTypeChoice: // choice _imp->setVisibleAnimates(true); _imp->setVisibleEvaluate(true); _imp->setVisibleHide(true); @@ -994,9 +1113,9 @@ AddKnobDialog::onTypeCurrentIndexChanged(int index) _imp->setVisibleSequence(false); _imp->setVisibleGrpAsTab(false); _imp->setVisibleParent(true); - _imp->setVisibleDefaultValues(true,AddKnobDialogPrivate::eDefaultValueTypeInt,1); + _imp->setVisibleDefaultValues(true, AddKnobDialogPrivate::eDefaultValueTypeString, d); break; - case 9: // bool + case eParamDataTypeCheckbox: // bool _imp->setVisibleAnimates(true); _imp->setVisibleEvaluate(true); _imp->setVisibleHide(true); @@ -1009,9 +1128,9 @@ AddKnobDialog::onTypeCurrentIndexChanged(int index) _imp->setVisibleSequence(false); _imp->setVisibleGrpAsTab(false); _imp->setVisibleParent(true); - _imp->setVisibleDefaultValues(true,AddKnobDialogPrivate::eDefaultValueTypeBool,1); + _imp->setVisibleDefaultValues(true, AddKnobDialogPrivate::eDefaultValueTypeBool, d); break; - case 10: // label + case eParamDataTypeLabel: // label _imp->setVisibleAnimates(false); _imp->setVisibleEvaluate(false); _imp->setVisibleHide(true); @@ -1024,9 +1143,9 @@ AddKnobDialog::onTypeCurrentIndexChanged(int index) _imp->setVisibleSequence(false); _imp->setVisibleGrpAsTab(false); _imp->setVisibleParent(true); - _imp->setVisibleDefaultValues(true,AddKnobDialogPrivate::eDefaultValueTypeString,1); + _imp->setVisibleDefaultValues(true, AddKnobDialogPrivate::eDefaultValueTypeString, d); break; - case 11: // text input + case eParamDataTypeTextInput: // text input _imp->setVisibleAnimates(true); _imp->setVisibleEvaluate(true); _imp->setVisibleHide(true); @@ -1039,10 +1158,10 @@ AddKnobDialog::onTypeCurrentIndexChanged(int index) _imp->setVisibleSequence(false); _imp->setVisibleGrpAsTab(false); _imp->setVisibleParent(true); - _imp->setVisibleDefaultValues(true,AddKnobDialogPrivate::eDefaultValueTypeString,1); + _imp->setVisibleDefaultValues(true, AddKnobDialogPrivate::eDefaultValueTypeString, d); break; - case 12: // input file - case 13: // output file + case eParamDataTypeInputFile: // input file + case eParamDataTypeOutputFile: // output file _imp->setVisibleAnimates(false); _imp->setVisibleEvaluate(true); _imp->setVisibleHide(true); @@ -1055,9 +1174,9 @@ AddKnobDialog::onTypeCurrentIndexChanged(int index) _imp->setVisibleSequence(true); _imp->setVisibleGrpAsTab(false); _imp->setVisibleParent(true); - _imp->setVisibleDefaultValues(true,AddKnobDialogPrivate::eDefaultValueTypeString,1); + _imp->setVisibleDefaultValues(true, AddKnobDialogPrivate::eDefaultValueTypeString, d); break; - case 14: // path + case eParamDataTypeDirectory: // path _imp->setVisibleAnimates(false); _imp->setVisibleEvaluate(true); _imp->setVisibleHide(true); @@ -1070,9 +1189,9 @@ AddKnobDialog::onTypeCurrentIndexChanged(int index) _imp->setVisibleSequence(false); _imp->setVisibleGrpAsTab(false); _imp->setVisibleParent(true); - _imp->setVisibleDefaultValues(true,AddKnobDialogPrivate::eDefaultValueTypeString,1); + _imp->setVisibleDefaultValues(true, AddKnobDialogPrivate::eDefaultValueTypeString, d); break; - case 15: // grp + case eParamDataTypeGroup: // grp _imp->setVisibleAnimates(false); _imp->setVisibleEvaluate(false); _imp->setVisibleHide(true); @@ -1085,9 +1204,9 @@ AddKnobDialog::onTypeCurrentIndexChanged(int index) _imp->setVisibleSequence(false); _imp->setVisibleGrpAsTab(true); _imp->setVisibleParent(false); - _imp->setVisibleDefaultValues(false,AddKnobDialogPrivate::eDefaultValueTypeInt,1); + _imp->setVisibleDefaultValues(false, AddKnobDialogPrivate::eDefaultValueTypeInt, d); break; - case 16: // page + case eParamDataTypePage: // page _imp->setVisibleAnimates(false); _imp->setVisibleEvaluate(false); _imp->setVisibleHide(false); @@ -1100,9 +1219,9 @@ AddKnobDialog::onTypeCurrentIndexChanged(int index) _imp->setVisibleSequence(false); _imp->setVisibleGrpAsTab(false); _imp->setVisibleParent(false); - _imp->setVisibleDefaultValues(false,AddKnobDialogPrivate::eDefaultValueTypeInt,1); + _imp->setVisibleDefaultValues(false, AddKnobDialogPrivate::eDefaultValueTypeInt, d); break; - case 17: // button + case eParamDataTypeButton: // button _imp->setVisibleAnimates(false); _imp->setVisibleEvaluate(false); _imp->setVisibleHide(false); @@ -1115,11 +1234,28 @@ AddKnobDialog::onTypeCurrentIndexChanged(int index) _imp->setVisibleSequence(false); _imp->setVisibleGrpAsTab(false); _imp->setVisibleParent(true); - _imp->setVisibleDefaultValues(false,AddKnobDialogPrivate::eDefaultValueTypeInt,1); + _imp->setVisibleDefaultValues(false, AddKnobDialogPrivate::eDefaultValueTypeInt, d); break; default: break; } + + if (_imp->isKnobAlias) { + _imp->setVisibleAnimates(false); + _imp->setVisibleEvaluate(false); + _imp->setVisibleHide(false); + _imp->setVisibleMenuItems(false); + //_imp->setVisibleMinMax(false); + _imp->setVisibleStartNewLine(true); + _imp->setVisibleMultiLine(false); + _imp->setVisibleMultiPath(false); + _imp->setVisibleRichText(false); + _imp->setVisibleSequence(false); + _imp->setVisibleGrpAsTab(false); + _imp->setVisibleParent(true); + // _imp->setVisibleDefaultValues(false, AddKnobDialogPrivate::eDefaultValueTypeInt, d); + _imp->setVisiblePage(true); + } } AddKnobDialog::~AddKnobDialog() @@ -1133,114 +1269,81 @@ AddKnobDialog::getKnob() const return _imp->knob; } +template +void +AddKnobDialogPrivate::setKnobMinMax(KnobI* knob) +{ + int dim = knob->getDimension(); + + Knob* k = dynamic_cast*>(knob); + assert(k); + + std::vector mins(dim),dmins(dim); + std::vector maxs(dim),dmaxs(dim); + for (int i = 0; i < dim; ++i) { + mins[i] = minBox->value(); + dmins[i] = dminBox->value(); + maxs[i] = maxBox->value(); + dmaxs[i] = dmaxBox->value(); + } + k->setMinimumsAndMaximums(mins, maxs); + k->setDisplayMinimumsAndMaximums(dmins, dmaxs); + std::vector defValues; + if (dim >= 1) { + defValues.push_back(default0->value()); + } + if (dim >= 2) { + defValues.push_back(default1->value()); + } + if (dim >= 3) { + defValues.push_back(default2->value()); + } + if (dim >= 4) { + defValues.push_back(default3->value()); + } + for (U32 i = 0; i < defValues.size(); ++i) { + k->setDefaultValue(defValues[i],i); + } + +} + void -AddKnobDialogPrivate::createKnobFromSelection(int index,int optionalGroupIndex) +AddKnobDialogPrivate::createKnobFromSelection(int index, int optionalGroupIndex) { + ParamDataTypeEnum t = (ParamDataTypeEnum)index; assert(!knob); std::string label = labelLineEdit->text().toStdString(); - - switch (index) { - case 0: - case 1: - case 2: { + int dim = dataTypeDim(t); + switch (t) { + case eParamDataTypeInteger: + case eParamDataTypeInteger2D: + case eParamDataTypeInteger3D: { //int - int dim = index + 1; boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, dim, false); - std::vector mins(dim),dmins(dim); - std::vector maxs(dim),dmaxs(dim); - - for (int i = 0; i < dim; ++i) { - mins[i] = std::floor(minBox->value() + 0.5); - dmins[i] = std::floor(dminBox->value() + 0.5); - maxs[i] = std::floor(maxBox->value() + 0.5); - dmaxs[i] = std::floor(dmaxBox->value() + 0.5); - } - k->setMinimumsAndMaximums(mins, maxs); - k->setDisplayMinimumsAndMaximums(dmins, dmaxs); - std::vector defValues; - if (dim >= 1) { - defValues.push_back(default0->value()); - } - if (dim >= 2) { - defValues.push_back(default1->value()); - } - if (dim >= 3) { - defValues.push_back(default2->value()); - } - for (U32 i = 0; i < defValues.size(); ++i) { - k->setDefaultValue(defValues[i],i); - } + setKnobMinMax(k.get()); knob = k; - } break; - case 3: - case 4: - case 5: { + break; + } + case eParamDataTypeFloatingPoint: + case eParamDataTypeFloatingPoint2D: + case eParamDataTypeFloatingPoint3D: { //double int dim = index - 2; boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, dim, false); - std::vector mins(dim),dmins(dim); - std::vector maxs(dim),dmaxs(dim); - for (int i = 0; i < dim; ++i) { - mins[i] = minBox->value(); - dmins[i] = dminBox->value(); - maxs[i] = maxBox->value(); - dmaxs[i] = dmaxBox->value(); - } - k->setMinimumsAndMaximums(mins, maxs); - k->setDisplayMinimumsAndMaximums(dmins, dmaxs); - std::vector defValues; - if (dim >= 1) { - defValues.push_back(default0->value()); - } - if (dim >= 2) { - defValues.push_back(default1->value()); - } - if (dim >= 3) { - defValues.push_back(default2->value()); - } - for (U32 i = 0; i < defValues.size(); ++i) { - k->setDefaultValue(defValues[i],i); - } - - + setKnobMinMax(k.get()); knob = k; - } break; - case 6: - case 7: { + break; + } + case eParamDataTypeColorRGB: + case eParamDataTypeColorRGBA: { // color int dim = index - 3; boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, dim, false); - std::vector mins(dim),dmins(dim); - std::vector maxs(dim),dmaxs(dim); - for (int i = 0; i < dim; ++i) { - mins[i] = minBox->value(); - dmins[i] = dminBox->value(); - maxs[i] = maxBox->value(); - dmaxs[i] = dmaxBox->value(); - } - std::vector defValues; - if (dim >= 1) { - defValues.push_back(default0->value()); - } - if (dim >= 2) { - defValues.push_back(default1->value()); - } - if (dim >= 3) { - defValues.push_back(default2->value()); - } - if (dim >= 4) { - defValues.push_back(default3->value()); - } - for (U32 i = 0; i < defValues.size(); ++i) { - k->setDefaultValue(defValues[i],i); - } - - k->setMinimumsAndMaximums(mins, maxs); - k->setDisplayMinimumsAndMaximums(dmins, dmaxs); + setKnobMinMax(k.get()); knob = k; - } break; - case 8: { - + break; + } + case eParamDataTypeChoice: { boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, 1, false); QString entriesRaw = menuItemsEdit->toPlainText(); QTextStream stream(&entriesRaw); @@ -1266,21 +1369,38 @@ AddKnobDialogPrivate::createKnobFromSelection(int index,int optionalGroupIndex) } k->populateChoices(entries,helps); - int defValue = default0->value(); - if (defValue < (int)entries.size() && defValue >= 0) { - k->setDefaultValue(defValue); + std::string defValue = defaultStr->text().toStdString(); + int defIndex = -1; + for (std::size_t i = 0; i < entries.size(); ++i) { + if (entries[i] == defValue) { + defIndex = i; + break; + } + } + if (defIndex == -1) { + std::stringstream ss; + ss << '"'; + ss << defValue; + ss << '"'; + ss << " does not exist in the defined menu items"; + throw std::invalid_argument(ss.str()); + } + if (defIndex < (int)entries.size() && defIndex >= 0) { + k->setDefaultValue(defIndex); } knob = k; - } break; - case 9: { + break; + } + case eParamDataTypeCheckbox: { boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, 1, false); bool defValue = defaultBool->isChecked(); k->setDefaultValue(defValue); knob = k; - } break; - case 10: - case 11: { + break; + } + case eParamDataTypeLabel: + case eParamDataTypeTextInput: { boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, 1, false); if (multiLine->isChecked()) { k->setAsMultiLine(); @@ -1295,8 +1415,9 @@ AddKnobDialogPrivate::createKnobFromSelection(int index,int optionalGroupIndex) std::string defValue = defaultStr->text().toStdString(); k->setDefaultValue(defValue); knob = k; - } break; - case 12: { + break; + } + case eParamDataTypeInputFile: { boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, 1, false); if (sequenceDialog->isChecked()) { k->setAsInputImage(); @@ -1304,8 +1425,9 @@ AddKnobDialogPrivate::createKnobFromSelection(int index,int optionalGroupIndex) std::string defValue = defaultStr->text().toStdString(); k->setDefaultValue(defValue); knob = k; - } break; - case 13: { + break; + } + case eParamDataTypeOutputFile: { boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, 1, false); if (sequenceDialog->isChecked()) { k->setAsOutputImageFile(); @@ -1313,8 +1435,9 @@ AddKnobDialogPrivate::createKnobFromSelection(int index,int optionalGroupIndex) std::string defValue = defaultStr->text().toStdString(); k->setDefaultValue(defValue); knob = k; - } break; - case 14: { + break; + } + case eParamDataTypeDirectory: { boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, 1, false); if (multiPath->isChecked()) { k->setMultiPath(true); @@ -1323,7 +1446,7 @@ AddKnobDialogPrivate::createKnobFromSelection(int index,int optionalGroupIndex) k->setDefaultValue(defValue); knob = k; } break; - case 15: { + case eParamDataTypeGroup: { boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, 1, false); if (groupAsTab->isChecked()) { k->setAsTab(); @@ -1331,11 +1454,11 @@ AddKnobDialogPrivate::createKnobFromSelection(int index,int optionalGroupIndex) k->setDefaultValue(true); //< default to opened knob = k; } break; - case 16: { + case eParamDataTypePage: { boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, 1, false); knob = k; } break; - case 17: { + case eParamDataTypeButton: { boost::shared_ptr k = Natron::createKnob(panel->getHolder(), label, 1, false); knob = k; } break; @@ -1354,7 +1477,7 @@ AddKnobDialogPrivate::createKnobFromSelection(int index,int optionalGroupIndex) knob->setSecretByDefault(hideBox->isChecked()); - knob->setName(nameLineEdit->text().toStdString()); + knob->setName(nameLineEdit->text().toStdString(), true); knob->setHintToolTip(tooltipArea->toPlainText().toStdString()); bool addedInGrp = false; KnobGroup* selectedGrp = getSelectedGroup(); @@ -1369,20 +1492,21 @@ AddKnobDialogPrivate::createKnobFromSelection(int index,int optionalGroupIndex) if (index != 16 && parentPage && !addedInGrp) { - std::string selectedItem = parentPage->getCurrentIndexText().toStdString(); - if (selectedItem == NATRON_USER_MANAGED_KNOBS_PAGE) { - boost::shared_ptr userPage = panel->getUserPageKnob(); - userPage->addKnob(knob); - panel->setUserPageActiveIndex(); - } else { - for (std::list::iterator it = userPages.begin(); it != userPages.end(); ++it) { - if ((*it)->getName() == selectedItem) { - (*it)->addKnob(knob); - break; - } + boost::shared_ptr page = getSelectedPage(); + if (!page) { + page = panel->getOrCreateUserPageKnob(); + } + if (page) { + if (optionalGroupIndex != -1) { + page->insertKnob(optionalGroupIndex, knob); + } else { + page->addKnob(knob); + } + if (page->getName() == NATRON_USER_MANAGED_KNOBS_PAGE) { + panel->setUserPageActiveIndex(); } - } + } @@ -1411,6 +1535,25 @@ AddKnobDialogPrivate::getSelectedGroup() const return 0; } +boost::shared_ptr +AddKnobDialogPrivate::getSelectedPage() const +{ + if (parentPage) { + std::string selectedItem = parentPage->getCurrentIndexText().toStdString(); + if (selectedItem == NATRON_USER_MANAGED_KNOBS_PAGE) { + return panel->getUserPageKnob(); + } + for (std::list >::const_iterator it = userPages.begin(); it != userPages.end(); ++it) { + if ((*it)->getName() == selectedItem) { + return *it; + break; + } + } + + } + return boost::shared_ptr(); +} + void AddKnobDialog::onOkClicked() { @@ -1454,47 +1597,73 @@ AddKnobDialog::onOkClicked() } + Natron::EffectInstance* effect = 0; + + + { + KnobHolder* holder = _imp->panel->getHolder(); + assert(holder); + + NodeGroup* isHolderGroup = dynamic_cast(holder); + if (isHolderGroup) { + //Check if the group has a node with the exact same script name as the param script name, in which case we error + //otherwise the attribute on the python object would be overwritten + NodeList nodes = isHolderGroup->getNodes(); + for (NodeList::iterator it = nodes.begin(); it!=nodes.end(); ++it) { + if ((*it)->getScriptName() == stdName) { + Natron::errorDialog(tr("Error").toStdString(), tr("A parameter on a group cannot have the same script-name as a node within " + "the group for scripting purposes.") + .toStdString()); + return; + + } + } + } + } + ///Remove the previous knob, and recreate it. ///Index of the type in the combo - int index; + ParamDataTypeEnum t; ///Remember the old page in which to insert the knob KnobPage* oldParentPage = 0; ///If the knob was in a group, we need to place it at the same index - int oldIndexInGroup = -1; + int oldIndexInParent = -1; std::string oldKnobScriptName; std::vector > expressions; std::map,std::vector > > listenersExpressions; + + if (!_imp->knob) { assert(_imp->typeChoice); - index = _imp->typeChoice->activeIndex(); + t = (ParamDataTypeEnum)_imp->typeChoice->activeIndex(); } else { oldKnobScriptName = _imp->knob->getName(); - + effect = dynamic_cast(_imp->knob->getHolder()); oldParentPage = _imp->knob->getTopLevelPage(); - index = getChoiceIndexFromKnobType(_imp->knob.get()); + t = getChoiceIndexFromKnobType(_imp->knob.get()); boost::shared_ptr parent = _imp->knob->getParentKnob(); KnobGroup* isParentGrp = dynamic_cast(parent.get()); if (isParentGrp && isParentGrp == _imp->getSelectedGroup()) { std::vector > children = isParentGrp->getChildren(); for (U32 i = 0; i < children.size(); ++i) { if (children[i] == _imp->knob) { - oldIndexInGroup = i; + oldIndexInParent = i; break; } } } else { std::vector > children; - if (oldParentPage) { + if (oldParentPage && oldParentPage == _imp->getSelectedPage().get()) { children = oldParentPage->getChildren(); } for (U32 i = 0; i < children.size(); ++i) { if (children[i] == _imp->knob) { - oldIndexInGroup = i; + oldIndexInParent = i; break; } } @@ -1521,48 +1690,24 @@ AddKnobDialog::onOkClicked() listenersExpressions[*it] = exprs; } + _imp->panel->getHolder()->removeDynamicKnob(_imp->knob.get()); + if (!_imp->isKnobAlias) { - _imp->panel->getHolder()->removeDynamicKnob(_imp->knob.get()); _imp->knob.reset(); } } //if (!_imp->knob) { + if (!_imp->isKnobAlias) { - _imp->createKnobFromSelection(index, oldIndexInGroup); - assert(_imp->knob); - - if (oldParentPage && !_imp->knob->getParentKnob()) { - if (oldIndexInGroup == -1) { - oldParentPage->addKnob(_imp->knob); - } else { - oldParentPage->insertKnob(oldIndexInGroup, _imp->knob); - } - } - - //If startsNewLine is false, set the flag on the previous knob - bool startNewLine = _imp->startNewLineBox->isChecked(); - boost::shared_ptr parentKnob = _imp->knob->getParentKnob(); - if (parentKnob) { - KnobGroup* parentIsGrp = dynamic_cast(parentKnob.get()); - KnobPage* parentIsPage = dynamic_cast(parentKnob.get()); - assert(parentIsGrp || parentIsPage); - std::vector > children; - if (parentIsGrp) { - children = parentIsGrp->getChildren(); - } else if (parentIsPage) { - children = parentIsPage->getChildren(); - } - for (U32 i = 0; i < children.size(); ++i) { - if (children[i] == _imp->knob) { - if (i > 0) { - children[i - 1]->setAddNewLine(startNewLine); - } - break; - } - } + try { + _imp->createKnobFromSelection((int)t, oldIndexInParent); + } catch (const std::exception& e) { + Natron::errorDialog(tr("Error while creating parameter").toStdString(), e.what()); + return; } + assert(_imp->knob); if (_imp->originalKnobSerialization) { @@ -1582,12 +1727,99 @@ AddKnobDialog::onOkClicked() } // if (!_imp->isKnobAlias) { else { //Alias knobs can only have these properties changed - _imp->knob->setName(_imp->nameLineEdit->text().toStdString()); - _imp->knob->setLabel(_imp->labelLineEdit->text().toStdString()); - _imp->knob->setHintToolTip(_imp->tooltipArea->toPlainText().toStdString()); - Natron::EffectInstance* effect = dynamic_cast(_imp->knob->getHolder()); - if (effect) { - effect->getNode()->declarePythonFields(); + assert(effect); + boost::shared_ptr page = _imp->getSelectedPage(); + if (!page) { + page = _imp->panel->getOrCreateUserPageKnob(); + _imp->panel->setUserPageActiveIndex(); + } + KnobGroup* group = _imp->getSelectedGroup(); + boost::shared_ptr shrdGrp; + if (group) { + shrdGrp = boost::dynamic_pointer_cast(group->shared_from_this()); + } + + try { + _imp->knob = _imp->isKnobAlias->createDuplicateOnNode(effect, + page, + shrdGrp, + oldIndexInParent, + true, + stdName, + _imp->labelLineEdit->text().toStdString(), + _imp->tooltipArea->toPlainText().toStdString(), + false); + } catch (const std::exception& e) { + Natron::errorDialog(tr("Error while creating parameter").toStdString(), e.what()); + return; + } + + KnobColor* isColor = dynamic_cast(_imp->knob.get()); + KnobDouble* isDbl = dynamic_cast(_imp->knob.get()); + KnobInt* isInt = dynamic_cast(_imp->knob.get()); + Knob* isStr = dynamic_cast*>(_imp->knob.get()); + KnobGroup* isGrp = dynamic_cast(_imp->knob.get()); + KnobBool* isBool = dynamic_cast(_imp->knob.get()); + KnobChoice* isChoice = dynamic_cast(_imp->knob.get()); + if (isColor || isDbl) { + _imp->setKnobMinMax(_imp->knob.get()); + } else if (isInt) { + _imp->setKnobMinMax(_imp->knob.get()); + } else if (isStr) { + isStr->setDefaultValue(_imp->defaultStr->text().toStdString()); + } else if (isGrp) { + isGrp->setDefaultValue(true); + } else if (isBool) { + isBool->setDefaultValue(_imp->defaultBool->isChecked()); + } else if (isChoice) { + std::string defValue = _imp->defaultStr->text().toStdString(); + int defIndex = -1; + std::vector entries = isChoice->getEntries_mt_safe(); + for (std::size_t i = 0; i < entries.size(); ++i) { + if (entries[i] == defValue) { + defIndex = i; + break; + } + } + if (defIndex == -1) { + std::stringstream ss; + ss << '"'; + ss << defValue; + ss << '"'; + ss << " does not exist in the defined menu items"; + Natron::errorDialog(tr("Error while creating parameter").toStdString(), ss.str()); + return; + } + if (defIndex < (int)entries.size() && defIndex >= 0) { + isChoice->setDefaultValue(defIndex); + } + + + } + + + } + + //If startsNewLine is false, set the flag on the previous knob + bool startNewLine = _imp->startNewLineBox->isChecked(); + boost::shared_ptr parentKnob = _imp->knob->getParentKnob(); + if (parentKnob) { + KnobGroup* parentIsGrp = dynamic_cast(parentKnob.get()); + KnobPage* parentIsPage = dynamic_cast(parentKnob.get()); + assert(parentIsGrp || parentIsPage); + std::vector > children; + if (parentIsGrp) { + children = parentIsGrp->getChildren(); + } else if (parentIsPage) { + children = parentIsPage->getChildren(); + } + for (U32 i = 0; i < children.size(); ++i) { + if (children[i] == _imp->knob) { + if (i > 0) { + children[i - 1]->setAddNewLine(startNewLine); + } + break; + } } } @@ -1616,6 +1848,12 @@ AddKnobDialog::onOkClicked() accept(); } +void +AddKnobDialogPrivate::setVisibleLabel(bool visible) +{ + labelLineEdit->setVisible(visible); +} + void AddKnobDialogPrivate::setVisibleMinMax(bool visible) { @@ -1628,9 +1866,9 @@ AddKnobDialogPrivate::setVisibleMinMax(bool visible) dmaxLabel->setVisible(visible); dmaxBox->setVisible(visible); if (typeChoice) { - int type = typeChoice->activeIndex(); + ParamDataTypeEnum t = (ParamDataTypeEnum)typeChoice->activeIndex(); - if (type == 6 || type == 7) { + if (t == eParamDataTypeColorRGB || t == eParamDataTypeColorRGB) { // color range to 0-1 minBox->setValue(INT_MIN); maxBox->setValue(INT_MAX); @@ -1762,7 +2000,9 @@ AddKnobDialogPrivate::setVisiblePage(bool visible) } void -AddKnobDialogPrivate::setVisibleDefaultValues(bool visible,AddKnobDialogPrivate::DefaultValueType type,int dimensions) +AddKnobDialogPrivate::setVisibleDefaultValues(bool visible, + AddKnobDialogPrivate::DefaultValueType type, + int dimensions) { if (!visible) { defaultStr->setVisible(false); diff --git a/Gui/AddKnobDialog.h b/Gui/AddKnobDialog.h index ae8a2ed794..374798c7f1 100644 --- a/Gui/AddKnobDialog.h +++ b/Gui/AddKnobDialog.h @@ -25,19 +25,19 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(uninitialized) #include CLANG_DIAG_ON(uninitialized) -class KnobI; -class DockablePanel; +#include "Gui/GuiFwd.h" + struct AddKnobDialogPrivate; class AddKnobDialog : public QDialog diff --git a/Gui/AnimatedCheckBox.cpp b/Gui/AnimatedCheckBox.cpp index 0b024c63d1..cd00091949 100644 --- a/Gui/AnimatedCheckBox.cpp +++ b/Gui/AnimatedCheckBox.cpp @@ -100,6 +100,8 @@ AnimatedCheckBox::mousePressEvent(QMouseEvent* e) Q_EMIT clicked(checked); Q_EMIT toggled(checked); + } else { + QFrame::mousePressEvent(e); } } @@ -149,7 +151,9 @@ AnimatedCheckBox::paintEvent(QPaintEvent* e) ///Draw tick if (checked) { - if (readOnly) { + if (animation == 3) { + activeColor = Qt::black; + } else if (readOnly) { activeColor.setRgbF(0.5, 0.5, 0.5); } else if (altered) { double r,g,b; diff --git a/Gui/AnimatedCheckBox.h b/Gui/AnimatedCheckBox.h index d79089630c..23a9b5bedd 100644 --- a/Gui/AnimatedCheckBox.h +++ b/Gui/AnimatedCheckBox.h @@ -26,6 +26,7 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -34,6 +35,9 @@ CLANG_DIAG_ON(uninitialized) #include "Global/Macros.h" +#include "Gui/GuiFwd.h" + + class AnimatedCheckBox : public QFrame { diff --git a/Gui/AnimationButton.h b/Gui/AnimationButton.h index cb8592b673..7456956232 100644 --- a/Gui/AnimationButton.h +++ b/Gui/AnimationButton.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef ANIMATIONBUTTON_H #define ANIMATIONBUTTON_H @@ -26,15 +25,11 @@ #include // ***** END PYTHON BLOCK ***** -#include "Gui/Button.h" +#include "Global/Macros.h" -class QDragEnterEvent; -class QDragLeaveEvent; -class QMouseEvent; -class QDropEvent; -class QEvent; +#include "Gui/Button.h" +#include "Gui/GuiFwd.h" -class KnobGui; class AnimationButton : public Button diff --git a/Gui/AutoHideToolBar.h b/Gui/AutoHideToolBar.h index 5cbd59d91d..367faea72c 100644 --- a/Gui/AutoHideToolBar.h +++ b/Gui/AutoHideToolBar.h @@ -33,7 +33,8 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -class Gui; +#include "Gui/GuiFwd.h" + class AutoHideToolBar : public QToolBar diff --git a/Gui/BackDropGui.h b/Gui/BackDropGui.h index eb82311ad7..3061213bea 100644 --- a/Gui/BackDropGui.h +++ b/Gui/BackDropGui.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef Gui_BackDropGui_h #define Gui_BackDropGui_h @@ -26,15 +25,12 @@ #include // ***** END PYTHON BLOCK ***** -#include "Gui/NodeGui.h" +#include "Global/Macros.h" -class QVBoxLayout; +#include "Gui/NodeGui.h" +#include "Gui/GuiFwd.h" -class KnobString; -class NodeGraph; -class DockablePanel; -class NodeBackDropSerialization; struct BackDropGuiPrivate; class BackDropGui : public NodeGui { diff --git a/Gui/Button.h b/Gui/Button.h index 1738ede576..0aa18e02dc 100644 --- a/Gui/Button.h +++ b/Gui/Button.h @@ -26,12 +26,16 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) +#include "Gui/GuiFwd.h" + + class Button : public QPushButton { diff --git a/Gui/ChannelsComboBox.h b/Gui/ChannelsComboBox.h index fa732a99f1..c6b0a6ebe8 100644 --- a/Gui/ChannelsComboBox.h +++ b/Gui/ChannelsComboBox.h @@ -25,7 +25,10 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include "Gui/ComboBox.h" +#include "Gui/GuiFwd.h" class ChannelsComboBox : public ComboBox diff --git a/Gui/ClickableLabel.h b/Gui/ClickableLabel.h index a93bfa9a16..8cd9212a68 100644 --- a/Gui/ClickableLabel.h +++ b/Gui/ClickableLabel.h @@ -26,6 +26,7 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -33,8 +34,9 @@ CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Global/Macros.h" +#include "Gui/GuiFwd.h" -#include "Label.h" +#include "Gui/Label.h" namespace Natron { diff --git a/Gui/ComboBox.cpp b/Gui/ComboBox.cpp index ebf9092239..89af85673b 100644 --- a/Gui/ComboBox.cpp +++ b/Gui/ComboBox.cpp @@ -364,7 +364,7 @@ ComboBox::paintEvent(QPaintEvent* /*e*/) void ComboBox::mousePressEvent(QMouseEvent* e) { - if ( buttonDownIsLeft(e) && !_readOnly && _enabled ) { + if ( buttonDownIsLeft(e) && !_readOnly ) { _clicked = true; createMenu(); update(); diff --git a/Gui/ComboBox.h b/Gui/ComboBox.h index 6ae22f2c82..0dee314e8c 100644 --- a/Gui/ComboBox.h +++ b/Gui/ComboBox.h @@ -25,12 +25,15 @@ #include // ***** END PYTHON BLOCK ***** -#include #include "Global/Macros.h" + +#include + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -39,15 +42,12 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" +#include "Gui/GuiFwd.h" + #define DROP_DOWN_ICON_SIZE 6 -class QHBoxLayout; -class QMouseEvent; -class QAction; -class MenuWithToolTips; struct ComboBoxMenuNode { diff --git a/Gui/CurveEditor.h b/Gui/CurveEditor.h index 240bc478d1..aaf3ebd805 100644 --- a/Gui/CurveEditor.h +++ b/Gui/CurveEditor.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include @@ -37,37 +39,15 @@ CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Global/GlobalDefines.h" -#include "Global/Macros.h" + +#include "Engine/EngineFwd.h" #include "Gui/PanelWidget.h" #include "Gui/CurveSelection.h" #include "Gui/CurveEditorUndoRedo.h" +#include "Gui/GuiFwd.h" + -class RectD; -class NodeGui; -class QTreeWidget; -class QTreeWidgetItem; -class QVBoxLayout; -class CurveWidget; -class CurveEditor; -class Curve; -class CurveGui; -class QHBoxLayout; -class QSplitter; -class KnobGui; -class KnobI; -class BezierCP; -class Bezier; -class RotoDrawableItem; -class RotoStrokeItem; -class LineEdit; -class RotoItem; -class RotoContext; -class KeyFrame; -class Variant; -class Gui; -class QAction; -class TimeLine; /** * All nodes are tracked in the CurveEditor and they all have a NodeCurveEditorContext. diff --git a/Gui/CurveEditorUndoRedo.h b/Gui/CurveEditorUndoRedo.h index 8f344a03ce..7245ae3c91 100644 --- a/Gui/CurveEditorUndoRedo.h +++ b/Gui/CurveEditorUndoRedo.h @@ -25,31 +25,27 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include -#include "Global/Macros.h" -CLANG_DIAG_OFF(deprecated) -CLANG_DIAG_OFF(uninitialized) -#include // in QtGui on Qt4, in QtWidgets on Qt5 -CLANG_DIAG_ON(deprecated) -CLANG_DIAG_ON(uninitialized) + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #include #endif + +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) +#include // in QtGui on Qt4, in QtWidgets on Qt5 +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + #include "Engine/Curve.h" -namespace Transform -{ - struct Matrix3x3; -} -class CurveGui; -class KnobGui; -class Bezier; -class Curve; -class CurveWidget; -class NodeCurveEditorElement; +#include "Gui/GuiFwd.h" + struct SelectedKey { diff --git a/Gui/CurveGui.h b/Gui/CurveGui.h index c1f489307e..09a429dd2b 100644 --- a/Gui/CurveGui.h +++ b/Gui/CurveGui.h @@ -26,22 +26,23 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + +#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) +#include +#endif + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include // QObject #include // QColor CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) -#include -#endif + #include "Engine/Curve.h" // Curve + #include "Gui/CurveGui.h" // Curves +#include "Gui/GuiFwd.h" -class KnobGui; -class CurveWidget; -class Bezier; -class RotoContext; class CurveGui : public QObject diff --git a/Gui/CurveSelection.h b/Gui/CurveSelection.h index 9ecb802cdb..1efdcd23a8 100644 --- a/Gui/CurveSelection.h +++ b/Gui/CurveSelection.h @@ -15,16 +15,28 @@ * You should have received a copy of the GNU General Public License * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ + #ifndef CURVESELECTION_H #define CURVESELECTION_H +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + +#include "Global/Macros.h" + #include + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif -class CurveGui; +#include "Gui/GuiFwd.h" + + class CurveSelection { public: diff --git a/Gui/CurveWidget.cpp b/Gui/CurveWidget.cpp index d34e39accc..1dde68a657 100644 --- a/Gui/CurveWidget.cpp +++ b/Gui/CurveWidget.cpp @@ -30,7 +30,7 @@ GCC_DIAG_UNUSED_PRIVATE_FIELD_OFF // /opt/local/include/QtGui/qmime.h:119:10: warning: private field 'type' is not used [-Wunused-private-field] #include GCC_DIAG_UNUSED_PRIVATE_FIELD_ON -#include +#include #include #include #include diff --git a/Gui/CurveWidget.h b/Gui/CurveWidget.h index e17da07f02..edf3701144 100644 --- a/Gui/CurveWidget.h +++ b/Gui/CurveWidget.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) @@ -33,7 +35,6 @@ #endif #include "Global/GLIncludes.h" //! // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) @@ -32,8 +34,6 @@ #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -44,25 +44,7 @@ CLANG_DIAG_ON(uninitialized) #include "Gui/CurveEditorUndoRedo.h" // KeyPtr #include "Gui/CurveGui.h" // CurveGui - -class CurveSelection; -class QFont; -class Variant; -class TimeLine; -class KnobGui; -class CurveWidget; -class Button; -class LineEdit; -class SpinBox; -class Gui; -class Bezier; -class RotoContext; -class QVBoxLayout; -class QHBoxLayout; -namespace Natron { - class Label; -} - +#include "Gui/GuiFwd.h" class ImportExportCurveDialog diff --git a/Gui/CurveWidgetPrivate.h b/Gui/CurveWidgetPrivate.h index 1aba171d83..204cbb59c2 100644 --- a/Gui/CurveWidgetPrivate.h +++ b/Gui/CurveWidgetPrivate.h @@ -25,28 +25,24 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include "Global/GLIncludes.h" //! // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + +#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) +#include +#include +#endif + #include "Global/GLIncludes.h" //! CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) -#include -#include -#endif + #include "Engine/OverlaySupport.h" -class KnobGui; -namespace Natron { -class OfxParamOverlayInteract; -} +#include "Gui/GuiFwd.h" + + struct CustomParamInteractPrivate; class CustomParamInteract : public QGLWidget, public OverlaySupport diff --git a/Gui/DockablePanel.cpp b/Gui/DockablePanel.cpp index d0f6476a4a..9dc47ba5cc 100644 --- a/Gui/DockablePanel.cpp +++ b/Gui/DockablePanel.cpp @@ -572,6 +572,18 @@ DockablePanel::setUserPageActiveIndex() } } +void +DockablePanel::setPageActiveIndex(const boost::shared_ptr& page) +{ + for (int i = 0; i < _imp->_tabWidget->count(); ++i) { + if (_imp->_tabWidget->tabText(i) == page->getLabel().c_str()) { + _imp->_tabWidget->setCurrentIndex(i); + _imp->refreshPagesSecretness(); + break; + } + } +} + int DockablePanel::getPagesCount() const { @@ -1193,7 +1205,8 @@ DockablePanel::getUndoStack() const bool DockablePanel::isClosed() const { - QMutexLocker l(&_imp->_isClosedMutex); return _imp->_isClosed; + QMutexLocker l(&_imp->_isClosedMutex); + return _imp->_isClosed; } bool @@ -1598,25 +1611,29 @@ DockablePanel::onHideUnmodifiedButtonClicked(bool checked) } void -DockablePanel::scanForNewKnobs() +DockablePanel::scanForNewKnobs(bool restorePageIndex) { + std::list userPages; getUserPages(userPages); + QString curTabName; + if (_imp->_pagesEnabled) { + + if (restorePageIndex) { + curTabName = _imp->_tabWidget->tabText(_imp->_tabWidget->currentIndex()); + } + boost::shared_ptr page = getUserPageKnob(); - userPages.push_back(page.get()); + if (page) { + userPages.push_back(page.get()); + } for (std::list::iterator it = userPages.begin(); it != userPages.end(); ++it) { - PageMap::iterator foundPage = _imp->_pages.find((*it)->getLabel().c_str()); - if (foundPage != _imp->_pages.end()) { - foundPage->second.currentRow = 0; - std::vector > children = (*it)->getChildren(); - for (std::vector >::iterator it2 = children.begin(); it2 != children.end(); ++it2) { - deleteKnobGui(*it2); - } - } + deleteKnobGui((*it)->shared_from_this()); } + } else { std::vector > knobs = _imp->_holder->getKnobs(); @@ -1627,12 +1644,55 @@ DockablePanel::scanForNewKnobs() } _imp->initializeKnobVector(_imp->_holder->getKnobs(),NULL); - NodeSettingsPanel* isNodePanel = dynamic_cast(this); - /*if (isNodePanel) { - isNodePanel->getNode()->getNode()->declarePythonFields(); - }*/ + ///Refresh pages order + if (_imp->_pagesEnabled) { + std::list > orderedPages; + const std::vector >& knobs = _imp->_holder->getKnobs(); + + std::list pages; + for (std::vector >::const_iterator it = knobs.begin(); it != knobs.end(); ++it) { + KnobPage* isPage = dynamic_cast(it->get()); + if (isPage) { + pages.push_back(isPage); + } + } + for (std::list::iterator it = pages.begin(); it!=pages.end(); ++it) { + + PageMap::iterator foundPage = _imp->_pages.find((*it)->getLabel().c_str()); + if (foundPage != _imp->_pages.end()) { + if ((*it)->getChildren().size() > 0) { + foundPage->second.tab->show(); + orderedPages.push_back(std::make_pair(foundPage->second.tab,foundPage->first)); + } else { + foundPage->second.tab->hide(); + } + } + + } + + + _imp->_tabWidget->clear(); + + + int index = 0; + int i = 0; + for (std::list >::iterator it = orderedPages.begin(); it!=orderedPages.end(); ++it,++i) { + _imp->_tabWidget->addTab(it->first, it->second); + if (restorePageIndex && it->second == curTabName) { + index = i; + } + } + + if (index >= 0 && index < int(orderedPages.size())) { + _imp->_tabWidget->setCurrentIndex(index); + } + } + + NodeSettingsPanel* isNodePanel = dynamic_cast(this); + + ///Refresh the curve editor with potential new animated knobs if (isNodePanel) { boost::shared_ptr node = isNodePanel->getNode(); @@ -1700,11 +1760,17 @@ struct ManageUserParamsDialogPrivate } boost::shared_ptr -DockablePanel::getUserPageKnob() const +DockablePanel::getOrCreateUserPageKnob() const { return _imp->_holder->getOrCreateUserPageKnob(); } +boost::shared_ptr +DockablePanel::getUserPageKnob() const +{ + return _imp->_holder->getUserPageKnob(); +} + void DockablePanel::getUserPages(std::list& userPages) const { diff --git a/Gui/DockablePanel.h b/Gui/DockablePanel.h index 1142ce8daf..858ecbcd75 100644 --- a/Gui/DockablePanel.h +++ b/Gui/DockablePanel.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) @@ -33,8 +35,6 @@ #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -47,21 +47,8 @@ CLANG_DIAG_ON(uninitialized) #include "Engine/DockablePanelI.h" -class KnobI; -class KnobGui; -class KnobHolder; -class NodeGui; -class Gui; -class KnobPage; -class QVBoxLayout; -class Button; -class QUndoStack; -class QUndoCommand; -class QGridLayout; -class RotoPanel; -class MultiInstancePanel; -class QTabWidget; -class KnobGroup; +#include "Gui/GuiFwd.h" + /** * @brief An abstract class that defines a dockable properties panel that can be found in the Property bin pane. @@ -153,15 +140,18 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON void onGuiClosing(); - virtual void scanForNewKnobs() OVERRIDE FINAL; + virtual void scanForNewKnobs(bool restorePageIndex = true) OVERRIDE FINAL; void setUserPageActiveIndex(); + void setPageActiveIndex(const boost::shared_ptr& page); + + boost::shared_ptr getOrCreateUserPageKnob() const; boost::shared_ptr getUserPageKnob() const; void getUserPages(std::list& userPages) const; - void deleteKnobGui(const boost::shared_ptr& knob); + virtual void deleteKnobGui(const boost::shared_ptr& knob) OVERRIDE FINAL; int getPagesCount() const; diff --git a/Gui/DockablePanelPrivate.cpp b/Gui/DockablePanelPrivate.cpp index 31ea60fc35..62f3b817fe 100644 --- a/Gui/DockablePanelPrivate.cpp +++ b/Gui/DockablePanelPrivate.cpp @@ -712,18 +712,10 @@ DockablePanelPrivate::getOrCreatePage(KnobPage* page) tabLayout->setSpacing(NATRON_FORM_LAYOUT_LINES_SPACING); if (_tabWidget) { - if (name == NATRON_USER_MANAGED_KNOBS_PAGE_LABEL || (page && page->isUserKnob())) { - _tabWidget->insertTab(0,newTab,name); - _tabWidget->setCurrentIndex(0); - } else { - _tabWidget->addTab(newTab,name); - } + _tabWidget->addTab(newTab,name); } else { - if (name == NATRON_USER_MANAGED_KNOBS_PAGE_LABEL || (page && page->isUserKnob())) { - _horizLayout->insertWidget(0, newTab); - } else { - _horizLayout->addWidget(newTab); - } + _horizLayout->addWidget(newTab); + } diff --git a/Gui/DockablePanelPrivate.h b/Gui/DockablePanelPrivate.h index 490a636dba..1d379800af 100644 --- a/Gui/DockablePanelPrivate.h +++ b/Gui/DockablePanelPrivate.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) @@ -33,8 +35,6 @@ #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -47,34 +47,10 @@ CLANG_DIAG_ON(uninitialized) #include "Global/GlobalDefines.h" #include "Engine/DockablePanelI.h" + #include "Gui/DockablePanel.h" +#include "Gui/GuiFwd.h" -class QHBoxLayout; -class QVBoxLayout; -class QUndoStack; -class QUndoCommand; -class QGridLayout; -class QTabWidget; - -class KnobI; -class KnobGui; -class KnobHolder; -class NodeGui; -class Gui; -class KnobPage; -class Button; -class RotoPanel; -class MultiInstancePanel; -class KnobGroup; -class LineEdit; -class FloatingWidget; - -class VerticalColorBar; -class TabGroup; - -namespace Natron { - class Label; -} struct Page { diff --git a/Gui/DockablePanelTabWidget.h b/Gui/DockablePanelTabWidget.h index ab94ca0a27..30d594956f 100644 --- a/Gui/DockablePanelTabWidget.h +++ b/Gui/DockablePanelTabWidget.h @@ -33,9 +33,8 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -class QKeyEvent; +#include "Gui/GuiFwd.h" -class Gui; /** * @class This is to overcome an issue in QTabWidget : switching tab does not resize the QTabWidget. diff --git a/Gui/DopeSheet.cpp b/Gui/DopeSheet.cpp index f88b56a372..4e2e98c10b 100644 --- a/Gui/DopeSheet.cpp +++ b/Gui/DopeSheet.cpp @@ -514,7 +514,8 @@ std::vector > DopeSheet::getImportantNodes(DSNode *dsN for (NodeList::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { NodePtr childNode = (*it); - if (boost::shared_ptrisInDopeSheet = findDSNode(childNode.get())) { + boost::shared_ptrisInDopeSheet = findDSNode(childNode.get()); + if (isInDopeSheet) { ret.push_back(isInDopeSheet); } } @@ -931,13 +932,15 @@ void DopeSheet::onNodeNameChanged(const QString &name) { Natron::Node *node = qobject_cast(sender()); boost::shared_ptrdsNode = findDSNode(node); - - dsNode->getTreeItem()->setText(0, name); + if (dsNode) { + dsNode->getTreeItem()->setText(0, name); + } } void DopeSheet::onKeyframeSetOrRemoved() { - if (boost::shared_ptr dsKnob = findDSKnob(qobject_cast(sender()))) { + boost::shared_ptr dsKnob = findDSKnob(qobject_cast(sender())); + if (dsKnob) { Q_EMIT keyframeSetOrRemoved(dsKnob.get()); } @@ -1339,8 +1342,7 @@ void DopeSheetSelectionModel::onNodeAboutToBeRemoved(const boost::shared_ptrdopeSheet->findDSNode(knobContext->getInternalKnob()) == removed) { it = _imp->selectedKeyframes.erase(it); - } - else { + } else { ++it; } } @@ -1426,6 +1428,9 @@ DSNode::DSNode(DopeSheet *model, for (KnobsAndGuis::const_iterator it = knobs.begin(); it != knobs.end(); ++it) { boost::shared_ptr knob = it->first.lock(); + if (!knob) { + continue; + } KnobGui *knobGui = it->second; if (!knob->canAnimate() || !knob->isAnimationEnabled()) { diff --git a/Gui/DopeSheet.h b/Gui/DopeSheet.h index 100388f49e..827d46f013 100644 --- a/Gui/DopeSheet.h +++ b/Gui/DopeSheet.h @@ -25,22 +25,27 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #include #endif -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) +#include "Global/GlobalDefines.h" + #include "Engine/Curve.h" +#include "Engine/EngineFwd.h" + +#include "Gui/GuiFwd.h" -#include "Global/GlobalDefines.h" -#include "Global/Macros.h" #define kReaderParamNameFirstFrame "firstFrame" #define kReaderParamNameLastFrame "lastFrame" @@ -52,28 +57,14 @@ CLANG_DIAG_ON(uninitialized) #define kFrameRangeParamNameFrameRange "frameRange" #define kTimeOffsetParamNameTimeOffset "timeOffset" + + class DopeSheetPrivate; -class DopeSheetEditor; class DopeSheetSelectionModel; class DopeSheetSelectionModelPrivate; class DSKnobPrivate; class DSNodePrivate; -class Gui; -class HierarchyView; -class KnobI; -class KnobGui; -class NodeGroup; -class NodeGui; -class QUndoCommand; -class TimeLine; -namespace Transform { - struct Matrix3x3; -} -namespace Natron { -class Node; -} - -class DSKnob; + class DSNode; class DopeSheet; @@ -256,20 +247,21 @@ class DSKnob * * It is and should be used only to handle keyframe selections. */ -struct DopeSheetKey +class DopeSheetKey { - DopeSheetKey(const boost::shared_ptr &knob, const KeyFrame& kf) : - context(knob), - key(kf) +public: + DopeSheetKey(const boost::shared_ptr &knob, const KeyFrame& kf) + : context(knob) + , key(kf) { boost::shared_ptr knobContext = context.lock(); assert(knobContext); } - DopeSheetKey(const DopeSheetKey &other) : - context(other.context), - key(other.key) + DopeSheetKey(const DopeSheetKey &other) + : context(other.context) + , key(other.key) {} friend bool operator==(const DopeSheetKey &key, const DopeSheetKey &other) diff --git a/Gui/DopeSheetEditor.h b/Gui/DopeSheetEditor.h index 67989820f7..d819d6f69a 100644 --- a/Gui/DopeSheetEditor.h +++ b/Gui/DopeSheetEditor.h @@ -25,11 +25,13 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -37,12 +39,9 @@ CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Gui/PanelWidget.h" +#include "Gui/GuiFwd.h" class DopeSheetEditorPrivate; -class Gui; -class DopeSheetView; -class NodeGui; -class TimeLine; /** * @class DopeSheetEditor diff --git a/Gui/DopeSheetEditorUndoRedo.h b/Gui/DopeSheetEditorUndoRedo.h index bbc9b88b7c..67d054ed18 100644 --- a/Gui/DopeSheetEditorUndoRedo.h +++ b/Gui/DopeSheetEditorUndoRedo.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include @@ -32,23 +34,19 @@ #include #include #endif -#include "Global/Enums.h" -#include "Global/Macros.h" -#include "Engine/Transform.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include // in QtGui on Qt4, in QtWidgets on Qt5 CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -class DopeSheetEditor; -class DSNode; -class Curve; -class DSKnob; -struct DopeSheetKey; -namespace Natron { -class Node; -} +#include "Global/Enums.h" + +#include "Engine/Transform.h" + +#include "Gui/GuiFwd.h" + typedef boost::shared_ptr DSKeyPtr; typedef std::list DSKeyPtrList; diff --git a/Gui/DopeSheetHierarchyView.cpp b/Gui/DopeSheetHierarchyView.cpp index 2c83c84cce..f44db7362d 100644 --- a/Gui/DopeSheetHierarchyView.cpp +++ b/Gui/DopeSheetHierarchyView.cpp @@ -526,8 +526,11 @@ void HierarchyViewPrivate::drawNodeTopSeparation(QPainter *p, QTreeWidgetItem *i int lineWidth = (appPTR->getCurrentSettings()->getDopeSheetEditorNodeSeparationWith() / 2); int lineBegin = q_ptr->rect().left(); - if (boost::shared_ptr parentNode = dopeSheetModel->mapNameItemToDSNode(item->parent())) { - lineBegin = getBranchRect(parentNode->getTreeItem()).right() + 2; + { + boost::shared_ptr parentNode = dopeSheetModel->mapNameItemToDSNode(item->parent()); + if (parentNode) { + lineBegin = getBranchRect(parentNode->getTreeItem()).right() + 2; + } } QPen pen(Qt::black); @@ -548,9 +551,12 @@ void HierarchyViewPrivate::drawNodeBottomSeparation(QPainter *p, boost::shared_p if (dsNode->getTreeItem()->isExpanded()) { lineBegin = getBranchRect(dsNode->getTreeItem()).right() + 2; } - } - else if (boost::shared_ptr parentNode = dopeSheetModel->mapNameItemToDSNode(nodeBelow->getTreeItem()->parent())) { - lineBegin = getBranchRect(parentNode->getTreeItem()).right() + 2; + + } else { + boost::shared_ptr parentNode = dopeSheetModel->mapNameItemToDSNode(nodeBelow->getTreeItem()->parent()); + if (parentNode) { + lineBegin = getBranchRect(parentNode->getTreeItem()).right() + 2; + } } QPen pen(Qt::black); @@ -774,8 +780,11 @@ void HierarchyView::drawRow(QPainter *painter, const QStyleOptionViewItem &optio _imp->drawNodeTopSeparation(painter, item, rowRect); } - if (boost::shared_ptr nodeBelow = _imp->itemBelowIsNode(item)) { - _imp->drawNodeBottomSeparation(painter, dsNode, nodeBelow, rowRect); + { + boost::shared_ptr nodeBelow = _imp->itemBelowIsNode(item); + if (nodeBelow) { + _imp->drawNodeBottomSeparation(painter, dsNode, nodeBelow, rowRect); + } } painter->restore(); diff --git a/Gui/DopeSheetHierarchyView.h b/Gui/DopeSheetHierarchyView.h index 8664973b16..f8d1f9e2f4 100644 --- a/Gui/DopeSheetHierarchyView.h +++ b/Gui/DopeSheetHierarchyView.h @@ -25,29 +25,26 @@ #include // ***** END PYTHON BLOCK ***** -#include "Global/GLIncludes.h" //! +#include +#endif + +#include "Global/GLIncludes.h" //! #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) -#include -#include -#endif +#include "Gui/GuiFwd.h" -class DopeSheet; -class DSKnob; -class HierarchyView; -class DSNode; -class Gui; -class HierarchyViewPrivate; -class QModelIndex; -class QStyleOptionViewItem; +class HierarchyViewPrivate; /** * @brief This class is a part of the hierarchy view. diff --git a/Gui/DopeSheetView.cpp b/Gui/DopeSheetView.cpp index 89b0a2364b..9c52df40a8 100644 --- a/Gui/DopeSheetView.cpp +++ b/Gui/DopeSheetView.cpp @@ -956,8 +956,11 @@ void DopeSheetViewPrivate::drawRows() const drawKnobRow(dsKnob); } - if (boost::shared_ptr group = model->getGroupDSNode(dsNode.get())) { - drawGroupOverlay(dsNode, group); + { + boost::shared_ptr group = model->getGroupDSNode(dsNode.get()); + if (group) { + drawGroupOverlay(dsNode, group); + } } Natron::DopeSheetItemType nodeType = dsNode->getItemType(); @@ -1272,19 +1275,22 @@ void DopeSheetViewPrivate::drawKeyframes(const boost::shared_ptr &dsNode } // Fill the knob times map - if (boost::shared_ptr rootDSKnob = model->mapNameItemToDSKnob(knobTreeItem->parent())) { - assert(rootDSKnob); - const std::map& map = knobsKeytimes[rootDSKnob.get()]; - bool knobTimeExists = (map.find(keyTime) != map.end()); - - if (!knobTimeExists) { - knobsKeytimes[rootDSKnob.get()][keyTime] = kfSelected; - } - else { - bool knobTimeIsSelected = knobsKeytimes[rootDSKnob.get()][keyTime]; + { + boost::shared_ptr rootDSKnob = model->mapNameItemToDSKnob(knobTreeItem->parent()); + if (rootDSKnob) { + assert(rootDSKnob); + const std::map& map = knobsKeytimes[rootDSKnob.get()]; + bool knobTimeExists = (map.find(keyTime) != map.end()); + + if (!knobTimeExists) { + knobsKeytimes[rootDSKnob.get()][keyTime] = kfSelected; + } + else { + bool knobTimeIsSelected = knobsKeytimes[rootDSKnob.get()][keyTime]; - if (!knobTimeIsSelected && kfSelected) { - knobsKeytimes[rootDSKnob.get()][keyTime] = true; + if (!knobTimeIsSelected && kfSelected) { + knobsKeytimes[rootDSKnob.get()][keyTime] = true; + } } } } @@ -1838,12 +1844,17 @@ void DopeSheetViewPrivate::computeReaderRange(DSNode *reader) nodeRanges[reader] = range; - if (boost::shared_ptr isInGroup = model->getGroupDSNode(reader)) { - computeGroupRange(isInGroup.get()); + { + boost::shared_ptr isInGroup = model->getGroupDSNode(reader); + if (isInGroup) { + computeGroupRange(isInGroup.get()); + } } - - if (boost::shared_ptr isConnectedToTimeNode = model->getNearestTimeNodeFromOutputs(reader)) { - computeNodeRange(isConnectedToTimeNode.get()); + { + boost::shared_ptr isConnectedToTimeNode = model->getNearestTimeNodeFromOutputs(reader); + if (isConnectedToTimeNode) { + computeNodeRange(isConnectedToTimeNode.get()); + } } --rangeComputationRecursion; @@ -1915,17 +1926,20 @@ void DopeSheetViewPrivate::computeTimeOffsetRange(DSNode *timeOffset) FrameRange range(0, 0); // Retrieve nearest reader useful values - if (boost::shared_ptr nearestReader = model->findDSNode(model->getNearestReader(timeOffset))) { - FrameRange nearestReaderRange = nodeRanges.at(nearestReader.get()); + { + boost::shared_ptr nearestReader = model->findDSNode(model->getNearestReader(timeOffset)); + if (nearestReader) { + FrameRange nearestReaderRange = nodeRanges.at(nearestReader.get()); - // Retrieve the time offset values - Knob *timeOffsetKnob = dynamic_cast *>(timeOffset->getInternalNode()->getKnobByName(kReaderParamNameTimeOffset).get()); - assert(timeOffsetKnob); + // Retrieve the time offset values + Knob *timeOffsetKnob = dynamic_cast *>(timeOffset->getInternalNode()->getKnobByName(kReaderParamNameTimeOffset).get()); + assert(timeOffsetKnob); - int timeOffsetValue = timeOffsetKnob->getValue(); + int timeOffsetValue = timeOffsetKnob->getValue(); - range.first = nearestReaderRange.first + timeOffsetValue; - range.second = nearestReaderRange.second + timeOffsetValue; + range.first = nearestReaderRange.first + timeOffsetValue; + range.second = nearestReaderRange.second + timeOffsetValue; + } } nodeRanges[timeOffset] = range; @@ -2833,15 +2847,21 @@ void DopeSheetView::onNodeAdded(DSNode *dsNode) _imp->computeNodeRange(dsNode); } - if (boost::shared_ptr parentGroupDSNode = _imp->model->getGroupDSNode(dsNode)) { - _imp->computeGroupRange(parentGroupDSNode.get()); + { + boost::shared_ptr parentGroupDSNode = _imp->model->getGroupDSNode(dsNode); + if (parentGroupDSNode) { + _imp->computeGroupRange(parentGroupDSNode.get()); + } } } void DopeSheetView::onNodeAboutToBeRemoved(DSNode *dsNode) { - if (boost::shared_ptr parentGroupDSNode = _imp->model->getGroupDSNode(dsNode)) { - _imp->computeGroupRange(parentGroupDSNode.get()); + { + boost::shared_ptr parentGroupDSNode = _imp->model->getGroupDSNode(dsNode); + if (parentGroupDSNode) { + _imp->computeGroupRange(parentGroupDSNode.get()); + } } std::map::iterator toRemove = _imp->nodeRanges.find(dsNode); @@ -2861,19 +2881,27 @@ void DopeSheetView::onKeyframeChanged() boost::shared_ptr dsNode; - if (KnobSignalSlotHandler *knobHandler = qobject_cast(signalSender)) { - dsNode = _imp->model->findDSNode(knobHandler->getKnob()); - } - else if (KnobGui *knobGui = qobject_cast(signalSender)) { - dsNode = _imp->model->findDSNode(knobGui->getKnob()); + { + KnobSignalSlotHandler *knobHandler = qobject_cast(signalSender); + if (knobHandler) { + dsNode = _imp->model->findDSNode(knobHandler->getKnob()); + } else { + KnobGui *knobGui = qobject_cast(signalSender); + if (knobGui) { + dsNode = _imp->model->findDSNode(knobGui->getKnob()); + } + } } if (!dsNode) { return; } - if (boost::shared_ptr parentGroupDSNode = _imp->model->getGroupDSNode(dsNode.get())) { - _imp->computeGroupRange(parentGroupDSNode.get()); + { + boost::shared_ptr parentGroupDSNode = _imp->model->getGroupDSNode(dsNode.get()); + if (parentGroupDSNode) { + _imp->computeGroupRange(parentGroupDSNode.get()); + } } } @@ -2883,17 +2911,18 @@ void DopeSheetView::onRangeNodeChanged(int /*dimension*/, int /*reason*/) boost::shared_ptr dsNode; - if (KnobSignalSlotHandler *knobHandler = qobject_cast(signalSender)) { - KnobHolder *holder = knobHandler->getKnob()->getHolder(); - Natron::EffectInstance *effectInstance = dynamic_cast(holder); - assert(effectInstance); - if (!effectInstance) { - return; + { + KnobSignalSlotHandler *knobHandler = qobject_cast(signalSender); + if (knobHandler) { + KnobHolder *holder = knobHandler->getKnob()->getHolder(); + Natron::EffectInstance *effectInstance = dynamic_cast(holder); + assert(effectInstance); + if (!effectInstance) { + return; + } + dsNode = _imp->model->findDSNode(effectInstance->getNode().get()); } - dsNode = _imp->model->findDSNode(effectInstance->getNode().get()); } - - assert(dsNode); if (!dsNode) { return; } @@ -2907,8 +2936,11 @@ void DopeSheetView::onRangeNodeChanged(int /*dimension*/, int /*reason*/) void DopeSheetView::onHierarchyViewItemExpandedOrCollapsed(QTreeWidgetItem *item) { // Compute the range rects of affected items - if (boost::shared_ptr dsNode = _imp->model->findParentDSNode(item)) { - _imp->computeRangesBelow(dsNode.get()); + { + boost::shared_ptr dsNode = _imp->model->findParentDSNode(item); + if (dsNode) { + _imp->computeRangesBelow(dsNode.get()); + } } _imp->computeSelectedKeysBRect(); diff --git a/Gui/DopeSheetView.h b/Gui/DopeSheetView.h index 187bd4f950..6b849c4160 100644 --- a/Gui/DopeSheetView.h +++ b/Gui/DopeSheetView.h @@ -25,11 +25,15 @@ #include // ***** END PYTHON BLOCK ***** -#include "Global/GLIncludes.h" //! +#include +#endif + +#include "Global/GLIncludes.h" //! CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) -#include -#include -#endif -class DopeSheet; -class DopeSheetViewPrivate; -class DSNode; -class Gui; -class HierarchyView; -class TimeLine; +#include "Engine/OverlaySupport.h" + +#include "Gui/GuiFwd.h" +class DopeSheetViewPrivate; + /** * @brief The DopeSheetView class describes the dope sheet view view of the * dope sheet editor. diff --git a/Gui/DotGui.cpp b/Gui/DotGui.cpp new file mode 100644 index 0000000000..71c3a6f149 --- /dev/null +++ b/Gui/DotGui.cpp @@ -0,0 +1,201 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * This file is part of Natron , + * Copyright (C) 2015 INRIA and Alexandre Gauthier-Foichat + * + * Natron is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Natron is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Natron. If not, see + * ***** END LICENSE BLOCK ***** */ + +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + +#include "DotGui.h" + +#include +#include // min, max + +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + +#include + +#include "Engine/BackDrop.h" +#include "Engine/Image.h" +#include "Engine/Knob.h" +#include "Engine/MergingEnum.h" +#include "Engine/Node.h" +#include "Engine/NodeSerialization.h" +#include "Engine/OfxEffectInstance.h" +#include "Engine/OfxImageEffectInstance.h" +#include "Engine/Plugin.h" +#include "Engine/Project.h" +#include "Engine/RotoLayer.h" +#include "Engine/Settings.h" +#include "Engine/ViewerInstance.h" + +#include "Gui/BackDropGui.h" +#include "Gui/Button.h" +#include "Gui/CurveEditor.h" +#include "Gui/HostOverlay.h" +#include "Gui/DockablePanel.h" +#include "Gui/DopeSheetEditor.h" +#include "Gui/Edge.h" +#include "Gui/Gui.h" +#include "Gui/GuiAppInstance.h" +#include "Gui/GuiApplicationManager.h" +#include "Gui/GuiDefines.h" +#include "Gui/KnobGui.h" +#include "Gui/KnobGuiString.h" +#include "Gui/Label.h" +#include "Gui/LineEdit.h" +#include "Gui/MultiInstancePanel.h" +#include "Gui/NodeGraph.h" +#include "Gui/NodeGraphUndoRedo.h" +#include "Gui/NodeGuiSerialization.h" +#include "Gui/NodeGraphTextItem.h" +#include "Gui/NodeSettingsPanel.h" +#include "Gui/SequenceFileDialog.h" +#include "Gui/SequenceFileDialog.h" +#include "Gui/SpinBox.h" +#include "Gui/Utils.h" +#include "Gui/ViewerGL.h" +#include "Gui/ViewerTab.h" + +#define NATRON_STATE_INDICATOR_OFFSET 5 + +#define NATRON_EDGE_DROP_TOLERANCE 15 + +#define NATRON_MAGNETIC_GRID_GRIP_TOLERANCE 20 + +#define NATRON_MAGNETIC_GRID_RELEASE_DISTANCE 30 + +#define NATRON_ELLIPSE_WARN_DIAMETER 10 + +#define NODE_WIDTH 80 +#define NODE_HEIGHT 30 + +#define DOT_GUI_DIAMETER 15 + +#define NATRON_PLUGIN_ICON_SIZE 20 +#define PLUGIN_ICON_OFFSET 2 + +using namespace Natron; + +using std::make_pair; + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327950288 /* pi */ +#endif + +//////////Dot node gui +DotGui::DotGui(QGraphicsItem* parent) +: NodeGui(parent) +, diskShape(NULL) +, ellipseIndicator(NULL) +{ +} + +void +DotGui::createGui() +{ + double depth = getBaseDepth(); + setZValue(depth); + + diskShape = new QGraphicsEllipseItem(this); + diskShape->setZValue(depth); + QPointF topLeft = mapFromParent( pos() ); + diskShape->setRect( QRectF(topLeft.x(),topLeft.y(),DOT_GUI_DIAMETER,DOT_GUI_DIAMETER) ); + + ellipseIndicator = new QGraphicsEllipseItem(this); + ellipseIndicator->setRect(QRectF(topLeft.x() - NATRON_STATE_INDICATOR_OFFSET, + topLeft.y() - NATRON_STATE_INDICATOR_OFFSET, + DOT_GUI_DIAMETER + NATRON_STATE_INDICATOR_OFFSET * 2, + DOT_GUI_DIAMETER + NATRON_STATE_INDICATOR_OFFSET * 2)); + ellipseIndicator->hide(); +} + +void +DotGui::refreshStateIndicator() +{ + bool showIndicator = true; + if (getIsSelected()) { + ellipseIndicator->setBrush(QColor(255,255,255,128)); + } else { + showIndicator = false; + } + + if (showIndicator && !ellipseIndicator->isVisible()) { + ellipseIndicator->show(); + } else if (!showIndicator && ellipseIndicator->isVisible()) { + ellipseIndicator->hide(); + } else { + update(); + } + +} + +void +DotGui::applyBrush(const QBrush & brush) +{ + diskShape->setBrush(brush); +} + +NodeSettingsPanel* +DotGui::createPanel(QVBoxLayout* container, + const boost::shared_ptr & thisAsShared) +{ + NodeSettingsPanel* panel = new NodeSettingsPanel( boost::shared_ptr(), + getDagGui()->getGui(), + thisAsShared, + container,container->parentWidget() ); + + ///Always close the panel by default for Dots + panel->setClosed(true); + + return panel; +} + +QRectF +DotGui::boundingRect() const +{ + QTransform t; + QRectF bbox = diskShape->boundingRect(); + QPointF center = bbox.center(); + + t.translate( center.x(), center.y() ); + t.scale( scale(), scale() ); + t.translate( -center.x(), -center.y() ); + + return t.mapRect(bbox); +} + +QPainterPath +DotGui::shape() const +{ + return diskShape->shape(); +} diff --git a/Gui/DotGui.h b/Gui/DotGui.h new file mode 100644 index 0000000000..1b24f18e1e --- /dev/null +++ b/Gui/DotGui.h @@ -0,0 +1,107 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * This file is part of Natron , + * Copyright (C) 2015 INRIA and Alexandre Gauthier-Foichat + * + * Natron is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Natron is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Natron. If not, see + * ***** END LICENSE BLOCK ***** */ + +#ifndef NATRON_GUI_NODEGUI_H +#define NATRON_GUI_NODEGUI_H + +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + +#include "Global/Macros.h" + +#include + +#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) +#include +#include +#include +#include +#endif + +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) +#include +#include +#include +#include +#include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + +#include "Global/GlobalDefines.h" + +#include "Gui/NodeGui.h" +#include "Gui/GuiFwd.h" + +class DotGui + : public NodeGui +{ +public: + + DotGui(QGraphicsItem *parent = 0); + +private: + + + virtual void createGui() OVERRIDE FINAL; + virtual NodeSettingsPanel* createPanel(QVBoxLayout* container, const boost::shared_ptr & thisAsShared) OVERRIDE FINAL WARN_UNUSED_RETURN; + virtual bool canMakePreview() OVERRIDE FINAL WARN_UNUSED_RETURN + { + return false; + } + + virtual void refreshStateIndicator() OVERRIDE FINAL; + + virtual void applyBrush(const QBrush & brush) OVERRIDE FINAL; + + virtual bool canResize() OVERRIDE FINAL WARN_UNUSED_RETURN { return false; } + + virtual QRectF boundingRect() const OVERRIDE FINAL; + virtual QPainterPath shape() const OVERRIDE FINAL; + QGraphicsEllipseItem* diskShape; + QGraphicsEllipseItem* ellipseIndicator; +}; + +struct ExportGroupTemplateDialogPrivate; +class ExportGroupTemplateDialog : public QDialog +{ + Q_OBJECT + +public: + + ExportGroupTemplateDialog(NodeCollection* group,Gui* gui,QWidget* parent); + + virtual ~ExportGroupTemplateDialog(); + +public Q_SLOTS: + + void onButtonClicked(); + + void onOkClicked(); + + void onLabelEditingFinished(); + +private: + + boost::scoped_ptr _imp; +}; + +#endif // NATRON_GUI_NODEGUI_H diff --git a/Gui/Edge.cpp b/Gui/Edge.cpp index 521e47be71..0531be0fc4 100644 --- a/Gui/Edge.cpp +++ b/Gui/Edge.cpp @@ -314,7 +314,7 @@ Edge::refreshState(bool hovered) boost::shared_ptr src = _imp->source.lock(); //The viewer does not hide its optional edges - bool isViewer = effect ? dynamic_cast(effect) : false; + bool isViewer = effect ? dynamic_cast(effect) != 0 : false; bool isReader = effect ? effect->isReader() : false; bool autoHide = areOptionalInputsAutoHidden(); bool isSelected = dst->getIsSelected(); diff --git a/Gui/Edge.h b/Gui/Edge.h index 5e9674ffef..04d4e6e17a 100644 --- a/Gui/Edge.h +++ b/Gui/Edge.h @@ -26,26 +26,21 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" -CLANG_DIAG_OFF(deprecated) -CLANG_DIAG_OFF(uninitialized) -#include -CLANG_DIAG_ON(deprecated) -CLANG_DIAG_ON(uninitialized) + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #include #endif -class QGraphicsPolygonItem; -class QGraphicsLineItem; -class QRectF; -class QPointF; -class QPainterPath; -class QGraphicsScene; -class QGraphicsTextItem; -class QGraphicsSceneMouseEvent; -class NodeGui; -class Node; + +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) +#include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + +#include "Gui/GuiFwd.h" + struct EdgePrivate; class Edge diff --git a/Gui/EditExpressionDialog.h b/Gui/EditExpressionDialog.h index 75f6c1b918..bc18aaabe7 100644 --- a/Gui/EditExpressionDialog.h +++ b/Gui/EditExpressionDialog.h @@ -25,19 +25,16 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include -#include "Global/Macros.h" - #include #include "Gui/EditScriptDialog.h" +#include "Gui/GuiFwd.h" -class QStringList; - -class QWidget; -class KnobGui; class EditExpressionDialog : public EditScriptDialog { diff --git a/Gui/EditScriptDialog.h b/Gui/EditScriptDialog.h index 4304fb7a9f..df9a5fb45d 100644 --- a/Gui/EditScriptDialog.h +++ b/Gui/EditScriptDialog.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // DBL_MAX #include // INT_MAX @@ -32,8 +34,6 @@ #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -42,8 +42,8 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) +#include "Gui/GuiFwd.h" -class QStringList; struct EditScriptDialogPrivate; class EditScriptDialog : public QDialog diff --git a/Gui/ExportGroupTemplateDialog.cpp b/Gui/ExportGroupTemplateDialog.cpp new file mode 100644 index 0000000000..c6633e072b --- /dev/null +++ b/Gui/ExportGroupTemplateDialog.cpp @@ -0,0 +1,304 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * This file is part of Natron , + * Copyright (C) 2015 INRIA and Alexandre Gauthier-Foichat + * + * Natron is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Natron is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Natron. If not, see + * ***** END LICENSE BLOCK ***** */ + +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + +#include "ExportGroupTemplateDialog.h" + +#include +#include // min, max +#include + +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) +#include +#include +#include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + +#include "Engine/NodeGroup.h" +#include "Engine/Settings.h" + +#include "Gui/Button.h" +#include "Gui/Gui.h" +#include "Gui/Label.h" +#include "Gui/LineEdit.h" +#include "Gui/SequenceFileDialog.h" +#include "Gui/GuiApplicationManager.h" +#include "Gui/Utils.h" // convertFromPlainText +#include "Gui/GuiDefines.h" + +struct ExportGroupTemplateDialogPrivate +{ + Gui* gui; + NodeCollection* group; + QGridLayout* mainLayout; + + Natron::Label* labelLabel; + LineEdit* labelEdit; + + Natron::Label* idLabel; + LineEdit* idEdit; + + Natron::Label* groupingLabel; + LineEdit* groupingEdit; + + Natron::Label* fileLabel; + LineEdit* fileEdit; + Button* openButton; + + Natron::Label* iconPathLabel; + LineEdit* iconPath; + + Natron::Label* descriptionLabel; + LineEdit* descriptionEdit; + + QDialogButtonBox *buttons; + + ExportGroupTemplateDialogPrivate(NodeCollection* group,Gui* gui) + : gui(gui) + , group(group) + , mainLayout(0) + , labelLabel(0) + , labelEdit(0) + , idLabel(0) + , idEdit(0) + , groupingLabel(0) + , groupingEdit(0) + , fileLabel(0) + , fileEdit(0) + , openButton(0) + , iconPathLabel(0) + , iconPath(0) + , descriptionLabel(0) + , descriptionEdit(0) + , buttons(0) + { + + } +}; + +ExportGroupTemplateDialog::ExportGroupTemplateDialog(NodeCollection* group,Gui* gui,QWidget* parent) +: QDialog(parent) +, _imp(new ExportGroupTemplateDialogPrivate(group,gui)) +{ + _imp->mainLayout = new QGridLayout(this); + + + _imp->idLabel = new Natron::Label(tr("Unique ID"),this); + QString idTt = Natron::convertFromPlainText(tr("The unique ID is used by " NATRON_APPLICATION_NAME "to identify the plug-in in various " + "places in the application. Generally this contains domain and sub-domains names " + "such as fr.inria.group.XXX. If 2 plug-ins happen to have the same ID they will be " + "gathered by version. If 2 plug-ins have the same ID and version, the first loaded in the" + " search-paths will take precedence over the other."), Qt::WhiteSpaceNormal); + _imp->idEdit = new LineEdit(this); + _imp->idEdit->setPlaceholderText("org.organization.pyplugs.XXX"); + _imp->idEdit->setToolTip(idTt); + + + _imp->labelLabel = new Natron::Label(tr("Label"),this); + QString labelTt = Natron::convertFromPlainText(tr("Set the label of the group as the user will see it in the user interface."), Qt::WhiteSpaceNormal); + _imp->labelLabel->setToolTip(labelTt); + _imp->labelEdit = new LineEdit(this); + _imp->labelEdit->setPlaceholderText("MyPlugin"); + QObject::connect(_imp->labelEdit,SIGNAL(editingFinished()), this , SLOT(onLabelEditingFinished())); + _imp->labelEdit->setToolTip(labelTt); + + + _imp->groupingLabel = new Natron::Label(tr("Grouping"),this); + QString groupingTt = Natron::convertFromPlainText(tr("The grouping of the plug-in specifies where the plug-in will be located in the menus. " + "E.g: Color/Transform, or Draw. Each sub-level must be separated by a '/'."), Qt::WhiteSpaceNormal); + _imp->groupingLabel->setToolTip(groupingTt); + + _imp->groupingEdit = new LineEdit(this); + _imp->groupingEdit->setPlaceholderText("Color/Transform"); + _imp->groupingEdit->setToolTip(groupingTt); + + + _imp->iconPathLabel = new Natron::Label(tr("Icon relative path"),this); + QString iconTt = Natron::convertFromPlainText(tr("Set here the file path of an optional icon to identify the plug-in. " + "The path is relative to the Python script."), Qt::WhiteSpaceNormal); + _imp->iconPathLabel->setToolTip(iconTt); + _imp->iconPath = new LineEdit(this); + _imp->iconPath->setPlaceholderText("Label.png"); + _imp->iconPath->setToolTip(iconTt); + + _imp->descriptionLabel = new Natron::Label(tr("Description"),this); + QString descTt = Natron::convertFromPlainText(tr("Set here the (optional) plug-in description that the user will see when clicking the " + " \"?\" button on the settings panel of the node."), Qt::WhiteSpaceNormal); + _imp->descriptionEdit = new LineEdit(this); + _imp->descriptionEdit->setToolTip(descTt); + _imp->descriptionEdit->setPlaceholderText(tr("This plug-in can be used to produce XXX effect...")); + + _imp->fileLabel = new Natron::Label(tr("Directory"),this); + QString fileTt = Natron::convertFromPlainText(tr("Specify here the directory where to export the Python script."), Qt::WhiteSpaceNormal); + _imp->fileLabel->setToolTip(fileTt); + _imp->fileEdit = new LineEdit(this); + + + _imp->fileEdit->setToolTip(fileTt); + + + QPixmap openPix; + appPTR->getIcon(Natron::NATRON_PIXMAP_OPEN_FILE, NATRON_MEDIUM_BUTTON_ICON_SIZE, &openPix); + _imp->openButton = new Button(QIcon(openPix),"",this); + _imp->openButton->setFocusPolicy(Qt::NoFocus); + _imp->openButton->setFixedSize(NATRON_MEDIUM_BUTTON_SIZE, NATRON_MEDIUM_BUTTON_SIZE); + QObject::connect( _imp->openButton, SIGNAL( clicked() ), this, SLOT( onButtonClicked() ) ); + + _imp->buttons = new QDialogButtonBox(QDialogButtonBox::StandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel), + Qt::Horizontal,this); + QObject::connect(_imp->buttons, SIGNAL(accepted()), this, SLOT(onOkClicked())); + QObject::connect(_imp->buttons, SIGNAL(rejected()), this, SLOT(reject())); + + + _imp->mainLayout->addWidget(_imp->idLabel, 0, 0 , 1 , 1); + _imp->mainLayout->addWidget(_imp->idEdit, 0, 1, 1 , 2); + _imp->mainLayout->addWidget(_imp->labelLabel, 1, 0 , 1 , 1); + _imp->mainLayout->addWidget(_imp->labelEdit, 1, 1, 1 , 2); + _imp->mainLayout->addWidget(_imp->groupingLabel, 2, 0, 1 , 1); + _imp->mainLayout->addWidget(_imp->groupingEdit, 2, 1, 1 , 2); + _imp->mainLayout->addWidget(_imp->iconPathLabel, 3, 0 , 1 , 1); + _imp->mainLayout->addWidget(_imp->iconPath, 3, 1 , 1 , 2); + _imp->mainLayout->addWidget(_imp->descriptionLabel, 4, 0 , 1 , 1); + _imp->mainLayout->addWidget(_imp->descriptionEdit, 4, 1 , 1 , 2); + _imp->mainLayout->addWidget(_imp->fileLabel, 5, 0 , 1 , 1); + _imp->mainLayout->addWidget(_imp->fileEdit, 5, 1, 1 , 1); + _imp->mainLayout->addWidget(_imp->openButton, 5, 2, 1, 1); + _imp->mainLayout->addWidget(_imp->buttons, 6, 0, 1, 3); + + resize(400,sizeHint().height()); + + +} + +ExportGroupTemplateDialog::~ExportGroupTemplateDialog() +{ + +} + +void +ExportGroupTemplateDialog::onButtonClicked() +{ + std::vector filters; + + const QString& path = _imp->gui->getLastPluginDirectory(); + SequenceFileDialog dialog(this, filters, false, SequenceFileDialog::eFileDialogModeDir, path.toStdString(), _imp->gui, false); + if (dialog.exec()) { + std::string selection = dialog.selectedFiles(); + _imp->fileEdit->setText(selection.c_str()); + QDir d = dialog.currentDirectory(); + _imp->gui->updateLastPluginDirectory(d.absolutePath()); + } +} + +void +ExportGroupTemplateDialog::onLabelEditingFinished() +{ + if (_imp->idEdit->text().isEmpty()) { + _imp->idEdit->setText(_imp->labelEdit->text()); + } +} + +void +ExportGroupTemplateDialog::onOkClicked() +{ + QString dirPath = _imp->fileEdit->text(); + + if (!dirPath.isEmpty() && dirPath[dirPath.size() - 1] == QChar('/')) { + dirPath.remove(dirPath.size() - 1, 1); + } + QDir d(dirPath); + + if (!d.exists()) { + Natron::errorDialog(tr("Error").toStdString(), tr("You must specify a directory to save the script").toStdString()); + return; + } + QString pluginLabel = _imp->labelEdit->text(); + if (pluginLabel.isEmpty()) { + Natron::errorDialog(tr("Error").toStdString(), tr("You must specify a label to name the script").toStdString()); + return; + } else { + pluginLabel = Natron::makeNameScriptFriendly(pluginLabel.toStdString()).c_str(); + } + + QString pluginID = _imp->idEdit->text(); + if (pluginID.isEmpty()) { + Natron::errorDialog(tr("Error").toStdString(), tr("You must specify a unique ID to identify the script").toStdString()); + return; + } + + QString iconPath = _imp->iconPath->text(); + QString grouping = _imp->groupingEdit->text(); + QString description = _imp->descriptionEdit->text(); + + QString filePath = d.absolutePath() + "/" + pluginLabel + ".py"; + + QStringList filters; + filters.push_back(QString(pluginLabel + ".py")); + if (!d.entryList(filters,QDir::Files | QDir::NoDotAndDotDot).isEmpty()) { + Natron::StandardButtonEnum rep = Natron::questionDialog(tr("Existing plug-in").toStdString(), + tr("A group plug-in with the same name already exists " + "would you like to " + "override it?").toStdString(), false); + if (rep == Natron::eStandardButtonNo) { + return; + } + } + + bool foundInPath = false; + QStringList groupSearchPath = appPTR->getAllNonOFXPluginsPaths(); + for (QStringList::iterator it = groupSearchPath.begin(); it != groupSearchPath.end(); ++it) { + if (!it->isEmpty() && it->at(it->size() - 1) == QChar('/')) { + it->remove(it->size() - 1, 1); + } + if (*it == dirPath) { + foundInPath = true; + } + } + + if (!foundInPath) { + + QString message = dirPath + tr(" does not exist in the group plug-in search path, would you like to add it?"); + Natron::StandardButtonEnum rep = Natron::questionDialog(tr("Plug-in path").toStdString(), + message.toStdString(), false); + + if (rep == Natron::eStandardButtonYes) { + appPTR->getCurrentSettings()->appendPythonGroupsPath(dirPath.toStdString()); + } + + } + + QFile file(filePath); + if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) { + Natron::errorDialog(tr("Error").toStdString(), QString(tr("Cannot open ") + filePath).toStdString()); + return; + } + + QTextStream ts(&file); + QString content; + _imp->group->exportGroupToPython(pluginID, pluginLabel, description, iconPath, grouping, content); + ts << content; + + accept(); +} diff --git a/Gui/ExportGroupTemplateDialog.h b/Gui/ExportGroupTemplateDialog.h new file mode 100644 index 0000000000..2a4db6d7ad --- /dev/null +++ b/Gui/ExportGroupTemplateDialog.h @@ -0,0 +1,69 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * This file is part of Natron , + * Copyright (C) 2015 INRIA and Alexandre Gauthier-Foichat + * + * Natron is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Natron is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Natron. If not, see + * ***** END LICENSE BLOCK ***** */ + +#ifndef Natron_Gui_ExportGroupTemplateDialog_h +#define Natron_Gui_ExportGroupTemplateDialog_h + +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + +#include "Global/Macros.h" + +#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) +#include +#endif + +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) +#include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + +#include "Global/GlobalDefines.h" + +#include "Gui/GuiFwd.h" + + +struct ExportGroupTemplateDialogPrivate; +class ExportGroupTemplateDialog : public QDialog +{ + Q_OBJECT + +public: + + ExportGroupTemplateDialog(NodeCollection* group, Gui* gui, QWidget* parent); + + virtual ~ExportGroupTemplateDialog(); + +public Q_SLOTS: + + void onButtonClicked(); + + void onOkClicked(); + + void onLabelEditingFinished(); + +private: + + boost::scoped_ptr _imp; +}; + +#endif // Natron_Gui_ExportGroupTemplateDialog_h diff --git a/Gui/FloatingWidget.cpp b/Gui/FloatingWidget.cpp index 98d887afa7..e188951402 100644 --- a/Gui/FloatingWidget.cpp +++ b/Gui/FloatingWidget.cpp @@ -51,9 +51,8 @@ FloatingWidget::FloatingWidget(Gui* gui, setAttribute(Qt::WA_DeleteOnClose, true); if (gui) { boost::shared_ptr project = gui->getApp()->getProject(); - QObject::connect(project.get(),SIGNAL(projectNameChanged(QString)), this, SLOT(onProjectNameChanged(QString))); - QString projectName = project->getProjectName(); - setWindowTitle(projectName); + QObject::connect(project.get(),SIGNAL(projectNameChanged(QString, bool)), this, SLOT(onProjectNameChanged(QString, bool))); + onProjectNameChanged(project->getProjectPath(), false); } _layout = new QVBoxLayout(this); _layout->setContentsMargins(0, 0, 0, 0); @@ -63,9 +62,13 @@ FloatingWidget::FloatingWidget(Gui* gui, } void -FloatingWidget::onProjectNameChanged(const QString& name) +FloatingWidget::onProjectNameChanged(const QString& filePath, bool modified) { - setWindowTitle(name); + // handles window title and appearance formatting + // http://doc.qt.io/qt-4.8/qwidget.html#windowModified-prop + setWindowModified(modified); + // http://doc.qt.io/qt-4.8/qwidget.html#windowFilePath-prop + setWindowFilePath(filePath); } static void diff --git a/Gui/FloatingWidget.h b/Gui/FloatingWidget.h index 18c848d398..02b9cf4f05 100644 --- a/Gui/FloatingWidget.h +++ b/Gui/FloatingWidget.h @@ -25,14 +25,14 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -40,63 +40,16 @@ CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Global/GlobalDefines.h" -#include "Gui/SerializableWindow.h" + #include "Engine/ScriptObject.h" +#include "Engine/EngineFwd.h" + +#include "Gui/SerializableWindow.h" +#include "Gui/GuiFwd.h" #define kMainSplitterObjectName "ToolbarSplitter" -//boost -namespace boost { -namespace archive { -class xml_iarchive; -class xml_oarchive; -} -} - -//QtGui -class Splitter; -class QUndoStack; -class QScrollArea; -class QToolButton; -class QVBoxLayout; -class QMutex; - -//Natron gui -class GuiLayoutSerialization; -class GuiAppInstance; -class NodeGui; -class TabWidget; -class ToolButton; -class ViewerTab; -class DockablePanel; -class NodeGraph; -class CurveEditor; -class Histogram; -class RotoGui; -class FloatingWidget; -class BoundAction; -class ScriptEditor; -class PyPanel; -class RectI; -class DopeSheetEditor; - -//Natron engine -class ViewerInstance; -class PluginGroupNode; -class KnobColor; -class ProcessHandler; -class NodeCollection; -class KnobHolder; -namespace Natron { -class Node; -class Image; -class EffectInstance; -class OutputEffectInstance; -} - -class Gui; - /*This class represents a floating pane that embeds a widget*/ class FloatingWidget : public QWidget, public SerializableWindow @@ -126,7 +79,7 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON public Q_SLOTS: - void onProjectNameChanged(const QString& name); + void onProjectNameChanged(const QString& filePath, bool modified); Q_SIGNALS: diff --git a/Gui/GlobalGuiWrapper.h b/Gui/GlobalGuiWrapper.h index d051c11ed2..5621d79896 100644 --- a/Gui/GlobalGuiWrapper.h +++ b/Gui/GlobalGuiWrapper.h @@ -19,12 +19,25 @@ #ifndef GLOBAL_GUI_WRAPPER_H #define GLOBAL_GUI_WRAPPER_H -#include "Engine/GlobalFunctionsWrapper.h" +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + +#include "Global/Macros.h" +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) #include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + +#include "Engine/GlobalFunctionsWrapper.h" #include "Gui/GuiAppWrapper.h" #include "Gui/GuiApplicationManager.h" +#include "Gui/GuiFwd.h" class PyGuiApplication : public PyCoreApplication { diff --git a/Gui/GroupBoxLabel.h b/Gui/GroupBoxLabel.h index d677755e95..464bbb363c 100644 --- a/Gui/GroupBoxLabel.h +++ b/Gui/GroupBoxLabel.h @@ -26,7 +26,10 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + #include "Gui/Label.h" +#include "Gui/GuiFwd.h" + namespace Natron { class GroupBoxLabel diff --git a/Gui/Gui.h b/Gui/Gui.h index 4cb8fdbb79..4d3fcde1f7 100644 --- a/Gui/Gui.h +++ b/Gui/Gui.h @@ -25,14 +25,14 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -40,76 +40,20 @@ CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Global/GlobalDefines.h" + +#include "Engine/ScriptObject.h" +#include "Engine/EngineFwd.h" + #include "Gui/SerializableWindow.h" #ifdef __NATRON_WIN32__ #include "Gui/FileTypeMainWindow_win.h" #endif -#include "Engine/ScriptObject.h" +#include "Gui/RegisteredTabs.h" +#include "Gui/GuiFwd.h" #define kMainSplitterObjectName "ToolbarSplitter" -//boost -namespace boost { -namespace archive { -class xml_iarchive; -class xml_oarchive; -} -} - -//QtGui -class Splitter; -class QUndoStack; -class QScrollArea; -class QToolButton; -class QVBoxLayout; -class QMutex; - -//Natron gui -#include "Gui/RegisteredTabs.h" -class GuiLayoutSerialization; -class GuiAppInstance; -class PanelWidget; -class AppInstance; -class NodeGui; -class TabWidget; -class ToolButton; -class ViewerTab; -class DockablePanel; -class NodeGraph; -class CurveEditor; -class Histogram; -class RotoGui; -class FloatingWidget; -class BoundAction; -class ScriptEditor; -class PyPanel; -class RectI; -class DopeSheetEditor; -class PropertiesBinWrapper; -class RenderStatsDialog; - -//Natron engine -class ViewerInstance; -class PluginGroupNode; -class KnobColor; -class ProcessHandler; -class NodeCollection; -class KnobHolder; -namespace Natron { -class Node; -class Image; -class EffectInstance; -class OutputEffectInstance; - - -#if defined(Q_OS_MAC) -//Implementation in Gui/QtMac.mm -bool isHighDPIInternal(const QWidget* w); -#endif - -} - struct GuiPrivate; @@ -155,8 +99,6 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON const std::list > & getSelectedNodes() const; - bool eventFilter(QObject *target, QEvent* e) OVERRIDE; - void createViewerGui(boost::shared_ptr viewer); void createGroupGui(const boost::shared_ptr& group, bool requestedByLoad); @@ -607,7 +549,14 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON void setLastKeyPressVisitedClickFocus(bool visited); void setApplicationConsoleActionVisible(bool visible); + +protected: + // Reimplemented Protected Functions + + //bool event(QEvent* event) OVERRIDE; + bool eventFilter(QObject *target, QEvent* e) OVERRIDE; + Q_SIGNALS: @@ -689,7 +638,7 @@ public Q_SLOTS: void openRecentFile(); - void onProjectNameChanged(const QString & name); + void onProjectNameChanged(const QString & filePath, bool modified); void onNodeNameChanged(const QString & name); @@ -738,10 +687,8 @@ public Q_SLOTS: void onShowApplicationConsoleActionTriggered(); - private: - void setCurrentPanelFocus(PanelWidget* widget); AppInstance* openProjectInternal(const std::string & absoluteFileName) WARN_UNUSED_RETURN; diff --git a/Gui/Gui.pro b/Gui/Gui.pro index 96d57c71c3..3d72f90dbe 100644 --- a/Gui/Gui.pro +++ b/Gui/Gui.pro @@ -92,9 +92,11 @@ SOURCES += \ DopeSheetEditorUndoRedo.cpp \ DopeSheetHierarchyView.cpp \ DopeSheetEditor.cpp \ + DotGui.cpp \ Edge.cpp \ EditExpressionDialog.cpp \ EditScriptDialog.cpp \ + ExportGroupTemplateDialog.cpp \ FloatingWidget.cpp \ QtEnumConvert.cpp \ Gui.cpp \ @@ -244,19 +246,22 @@ HEADERS += \ DopeSheetEditorUndoRedo.h \ DopeSheetHierarchyView.h \ DopeSheetEditor.h \ + DotGui.h \ Edge.h \ EditExpressionDialog.h \ EditScriptDialog.h \ + ExportGroupTemplateDialog.h \ FileTypeMainWindow_win.h \ FloatingWidget.h \ QtEnumConvert.h \ GroupBoxLabel.h \ Gui.h \ - GuiDefines.h \ GuiApplicationManager.h \ GuiApplicationManagerPrivate.h \ GuiAppInstance.h \ GuiAppWrapper.h \ + GuiDefines.h \ + GuiFwd.h \ GuiMacros.h \ GuiPrivate.h \ GlobalGuiWrapper.h \ diff --git a/Gui/Gui05.cpp b/Gui/Gui05.cpp index e529984a89..4ef2f70f3a 100644 --- a/Gui/Gui05.cpp +++ b/Gui/Gui05.cpp @@ -63,7 +63,8 @@ using namespace Natron; void Gui::setupUi() { - setWindowTitle( QCoreApplication::applicationName() ); + onProjectNameChanged(QString(), false); + setMouseTracking(true); installEventFilter(this); assert( !isFullScreen() ); @@ -137,7 +138,7 @@ Gui::setupUi() //the same action also clears the ofx plugins caches, they are not the same cache but are used to the same end boost::shared_ptr project = _imp->_appInstance->getProject(); - QObject::connect( project.get(), SIGNAL( projectNameChanged(QString) ), this, SLOT( onProjectNameChanged(QString) ) ); + QObject::connect( project.get(), SIGNAL( projectNameChanged(QString, bool) ), this, SLOT( onProjectNameChanged(QString, bool) ) ); boost::shared_ptr timeline = project->getTimeLine(); QObject::connect( timeline.get(),SIGNAL( frameChanged(SequenceTime,int) ), this,SLOT( onTimeChanged(SequenceTime,int) ) ); diff --git a/Gui/Gui20.cpp b/Gui/Gui20.cpp index ff590033f9..b90c531c64 100644 --- a/Gui/Gui20.cpp +++ b/Gui/Gui20.cpp @@ -1057,21 +1057,21 @@ Gui::saveProject() if (project->hasProjectBeenSavedByUser()) { - QString projectName = project->getProjectName(); + QString projectFilename = project->getProjectFilename(); QString projectPath = project->getProjectPath(); - if (!_imp->checkProjectLockAndWarn(projectPath,projectName)) { + if (!_imp->checkProjectLockAndWarn(projectPath, projectFilename)) { return false; } - bool ret = project->saveProject(projectPath, projectName, 0); + bool ret = project->saveProject(projectPath, projectFilename, 0); ///update the open recents if (!projectPath.endsWith('/')) { projectPath.append('/'); } if (ret) { - QString file = projectPath + projectName; + QString file = projectPath + projectFilename; updateRecentFiles(file); } return ret; @@ -1116,7 +1116,7 @@ void Gui::saveAndIncrVersion() { QString path = _imp->_appInstance->getProject()->getProjectPath(); - QString name = _imp->_appInstance->getProject()->getProjectName(); + QString name = _imp->_appInstance->getProject()->getProjectFilename(); int currentVersion = 0; int positionToInsertVersion; bool mustAppendFileExtension = false; @@ -1363,7 +1363,7 @@ Gui::saveWarning() { if ( !_imp->_appInstance->getProject()->isSaveUpToDate() ) { Natron::StandardButtonEnum ret = Natron::questionDialog(NATRON_APPLICATION_NAME, tr("Save changes to ").toStdString() + - _imp->_appInstance->getProject()->getProjectName().toStdString() + " ?", + _imp->_appInstance->getProject()->getProjectFilename().toStdString() + " ?", false, Natron::StandardButtons(Natron::eStandardButtonSave | Natron::eStandardButtonDiscard | Natron::eStandardButtonCancel), Natron::eStandardButtonSave); if ( (ret == Natron::eStandardButtonEscape) || (ret == Natron::eStandardButtonCancel) ) { diff --git a/Gui/Gui40.cpp b/Gui/Gui40.cpp index 6e2d450407..ee4906adc5 100644 --- a/Gui/Gui40.cpp +++ b/Gui/Gui40.cpp @@ -189,12 +189,13 @@ Gui::screenShot(QWidget* w) } void -Gui::onProjectNameChanged(const QString & name) +Gui::onProjectNameChanged(const QString & filePath, bool modified) { - QString text(QCoreApplication::applicationName() + " - "); - - text.append(name); - setWindowTitle(text); + // handles window title and appearance formatting + // http://doc.qt.io/qt-4.8/qwidget.html#windowModified-prop + setWindowModified(modified); + // http://doc.qt.io/qt-4.8/qwidget.html#windowFilePath-prop + setWindowFilePath(filePath.isEmpty() ? NATRON_PROJECT_UNTITLED : filePath); } void @@ -884,18 +885,17 @@ Gui::onTimeChanged(SequenceTime time, ViewerInstance* leadViewer = getApp()->getLastViewerUsingTimeline(); - bool isUserEdited = reason == eTimelineChangeReasonUserSeek || - reason == eTimelineChangeReasonDopeSheetEditorSeek || - reason == eTimelineChangeReasonCurveEditorSeek; + bool isPlayback = reason == eTimelineChangeReasonPlaybackSeek; const std::list& viewers = getViewersList(); ///Syncrhronize viewers for (std::list::const_iterator it = viewers.begin(); it!=viewers.end();++it) { - if ((*it)->getInternalNode() != leadViewer || isUserEdited) { - (*it)->getInternalNode()->renderCurrentFrame(reason != eTimelineChangeReasonPlaybackSeek); + if ((*it)->getInternalNode() == leadViewer && isPlayback) { + continue; } + (*it)->getInternalNode()->renderCurrentFrame(!isPlayback); } } diff --git a/Gui/Gui50.cpp b/Gui/Gui50.cpp index 44bce1272c..fbfdfb4ed0 100644 --- a/Gui/Gui50.cpp +++ b/Gui/Gui50.cpp @@ -68,6 +68,7 @@ GCC_DIAG_UNUSED_PRIVATE_FIELD_ON #include "Gui/ComboBox.h" #include "Gui/DockablePanel.h" #include "Gui/DopeSheetEditor.h" +#include "Gui/ExportGroupTemplateDialog.h" #include "Gui/GuiAppInstance.h" #include "Gui/GuiApplicationManager.h" // appPTR #include "Gui/GuiPrivate.h" diff --git a/Gui/GuiAppInstance.cpp b/Gui/GuiAppInstance.cpp index 4b48e6e1a2..d83c80d32f 100644 --- a/Gui/GuiAppInstance.cpp +++ b/Gui/GuiAppInstance.cpp @@ -34,6 +34,7 @@ #include "Engine/CLArgs.h" #include "Engine/Project.h" #include "Engine/EffectInstance.h" +#include "Engine/Image.h" #include "Engine/Node.h" #include "Engine/NodeGroup.h" #include "Engine/Plugin.h" @@ -57,6 +58,49 @@ using namespace Natron; +struct RotoPaintData +{ + boost::shared_ptr rotoPaintNode; + + boost::shared_ptr stroke; + + bool isPainting; + + bool turboAlreadyActiveBeforePainting; + + ///The last mouse event tick bounding box, to render the least possible + RectD lastStrokeMovementBbox; + + ///The index of the points/stroke we have rendered + int lastStrokeIndex,multiStrokeIndex; + + ///The last points of the mouse event + std::list > lastStrokePoints; + + ///Used for the rendering algorithm to know where we stopped along the path + double distToNextIn,distToNextOut; + + //The image used to render the currently drawn stroke mask + boost::shared_ptr strokeImage; + + RotoPaintData() + : rotoPaintNode() + , stroke() + , isPainting(false) + , turboAlreadyActiveBeforePainting(false) + , lastStrokeMovementBbox() + , lastStrokeIndex(-1) + , multiStrokeIndex(0) + , lastStrokePoints() + , distToNextIn(0) + , distToNextOut(0) + , strokeImage() + { + + } + +}; + struct GuiAppInstancePrivate { Gui* _gui; //< ptr to the Gui interface @@ -86,9 +130,8 @@ struct GuiAppInstancePrivate std::string declareAppAndParamsString; int overlayRedrawRequests; - mutable QMutex userIsPaintingMutex; - boost::shared_ptr userIsPainting; - bool turboAlreadyActiveBeforePainting; + mutable QMutex rotoDataMutex; + RotoPaintData rotoData; GuiAppInstancePrivate() : _gui(NULL) @@ -103,10 +146,10 @@ struct GuiAppInstancePrivate , loadProjectSplash(0) , declareAppAndParamsString() , overlayRedrawRequests(0) - , userIsPaintingMutex() - , userIsPainting() - , turboAlreadyActiveBeforePainting(false) + , rotoDataMutex() + , rotoData() { + rotoData.turboAlreadyActiveBeforePainting = false; } void findOrCreateToolButtonRecursive(const boost::shared_ptr& n); @@ -1141,26 +1184,46 @@ GuiAppInstance::isDraftRenderEnabled() const } void -GuiAppInstance::setUserIsPainting(const boost::shared_ptr& rotopaintNode) +GuiAppInstance::setUserIsPainting(const boost::shared_ptr& rotopaintNode, + const boost::shared_ptr& stroke, + bool isPainting) { bool wasTurboActive; { - QMutexLocker k(&_imp->userIsPaintingMutex); - _imp->userIsPainting = rotopaintNode; + QMutexLocker k(&_imp->rotoDataMutex); + + if (isPainting && (rotopaintNode != _imp->rotoData.rotoPaintNode || + stroke != _imp->rotoData.stroke)) { + _imp->rotoData.strokeImage.reset(); + } + + _imp->rotoData.isPainting = isPainting; + if (isPainting) { + _imp->rotoData.rotoPaintNode = rotopaintNode; + _imp->rotoData.stroke = stroke; + } + + + //Reset the index + _imp->rotoData.lastStrokeIndex = -1; if (rotopaintNode) { - _imp->turboAlreadyActiveBeforePainting = _imp->_gui->isGUIFrozen(); + _imp->rotoData.turboAlreadyActiveBeforePainting = _imp->_gui->isGUIFrozen(); } - wasTurboActive = _imp->turboAlreadyActiveBeforePainting; + wasTurboActive = _imp->rotoData.turboAlreadyActiveBeforePainting; } - bool isPainting = rotopaintNode.get() != 0; - _imp->_gui->onFreezeUIButtonClicked(isPainting || wasTurboActive); + //bool isPainting = rotopaintNode.get() != 0; + // _imp->_gui->onFreezeUIButtonClicked(isPainting || wasTurboActive); } -boost::shared_ptr -GuiAppInstance::getIsUserPainting() const +void +GuiAppInstance::getActiveRotoDrawingStroke(boost::shared_ptr* node, + boost::shared_ptr* stroke, + bool *isPainting) const { - QMutexLocker k(&_imp->userIsPaintingMutex); - return _imp->userIsPainting; + QMutexLocker k(&_imp->rotoDataMutex); + *node = _imp->rotoData.rotoPaintNode; + *stroke = _imp->rotoData.stroke; + *isPainting = _imp->rotoData.isPainting; } bool @@ -1232,4 +1295,66 @@ GuiAppInstance::getOfxHostOSHandle() const } WId ret = _imp->_gui->winId(); return (void*)ret; +} + + + +void +GuiAppInstance::updateLastPaintStrokeData(int newAge,const std::list >& points, + const RectD& lastPointsBbox, + int strokeIndex) +{ + + { + QMutexLocker k(&_imp->rotoDataMutex); + _imp->rotoData.lastStrokePoints = points; + _imp->rotoData.lastStrokeMovementBbox = lastPointsBbox; + _imp->rotoData.lastStrokeIndex = newAge; + _imp->rotoData.distToNextIn = _imp->rotoData.distToNextOut; + _imp->rotoData.multiStrokeIndex = strokeIndex; + } +} + +void +GuiAppInstance::getLastPaintStrokePoints(std::list > >* strokes, int* strokeIndex) const +{ + QMutexLocker k(&_imp->rotoDataMutex); + strokes->push_back(_imp->rotoData.lastStrokePoints); + *strokeIndex = _imp->rotoData.multiStrokeIndex; +} + +int +GuiAppInstance::getStrokeLastIndex() const +{ + QMutexLocker k(&_imp->rotoDataMutex); + return _imp->rotoData.lastStrokeIndex; +} + +void +GuiAppInstance::getRenderStrokeData(RectD* lastStrokeMovementBbox, std::list >* lastStrokeMovementPoints, + double *distNextIn, boost::shared_ptr* strokeImage) const +{ + QMutexLocker k(&_imp->rotoDataMutex); + *lastStrokeMovementBbox = _imp->rotoData.lastStrokeMovementBbox; + *lastStrokeMovementPoints = _imp->rotoData.lastStrokePoints; + *distNextIn = _imp->rotoData.distToNextIn; + *strokeImage = _imp->rotoData.strokeImage; +} + + +void +GuiAppInstance::updateStrokeImage(const boost::shared_ptr& image, double distNextOut, bool setDistNextOut) +{ + QMutexLocker k(&_imp->rotoDataMutex); + _imp->rotoData.strokeImage = image; + if (setDistNextOut) { + _imp->rotoData.distToNextOut = distNextOut; + } +} + +RectD +GuiAppInstance::getLastPaintStrokeBbox() const +{ + QMutexLocker k(&_imp->rotoDataMutex); + return _imp->rotoData.lastStrokeMovementBbox; } \ No newline at end of file diff --git a/Gui/GuiAppInstance.h b/Gui/GuiAppInstance.h index dd610c5087..c3f47bb0b2 100644 --- a/Gui/GuiAppInstance.h +++ b/Gui/GuiAppInstance.h @@ -25,24 +25,22 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include "Engine/AppInstance.h" -#include "Global/Macros.h" +#include "Gui/GuiFwd.h" -class NodeGui; -class Gui; -class ViewerTab; -class Format; -class KnobHolder; /** * @brief This little struct contains what enables file dialogs to show previews. * It is shared by all dialogs so that we don't have to recreate the nodes everytimes **/ -struct FileDialogPreviewProvider +class FileDialogPreviewProvider { +public: ViewerTab* viewerUI; boost::shared_ptr viewerNodeInternal; boost::shared_ptr viewerNode; @@ -197,8 +195,6 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON virtual bool isDraftRenderEnabled() const OVERRIDE FINAL WARN_UNUSED_RETURN; - virtual void setUserIsPainting(const boost::shared_ptr& rotopaintNode) OVERRIDE FINAL; - virtual boost::shared_ptr getIsUserPainting() const OVERRIDE FINAL WARN_UNUSED_RETURN; virtual bool isRenderStatsActionChecked() const OVERRIDE FINAL; @@ -217,11 +213,38 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON virtual AppInstance* newProject() OVERRIDE FINAL; void handleFileOpenEvent(const std::string& filename); + +public: virtual void* getOfxHostOSHandle() const OVERRIDE FINAL; -private: + + ///Rotopaint related + virtual void updateLastPaintStrokeData(int newAge, + const std::list >& points, + const RectD& lastPointsBbox, + int strokeIndex) OVERRIDE FINAL; + + virtual void getLastPaintStrokePoints(std::list > >* strokes, int* strokeIndex) const OVERRIDE FINAL; + + virtual void getRenderStrokeData(RectD* lastStrokeMovementBbox, std::list >* lastStrokeMovementPoints, + double *distNextIn, boost::shared_ptr* strokeImage) const OVERRIDE FINAL; + + virtual int getStrokeLastIndex() const OVERRIDE FINAL; + + virtual void updateStrokeImage(const boost::shared_ptr& image, double distNextOut, bool setDistNextOut) OVERRIDE FINAL; + virtual RectD getLastPaintStrokeBbox() const OVERRIDE FINAL; + + virtual void setUserIsPainting(const boost::shared_ptr& rotopaintNode, + const boost::shared_ptr& stroke, + bool isPainting) OVERRIDE FINAL; + virtual void getActiveRotoDrawingStroke(boost::shared_ptr* node, + boost::shared_ptr* stroke, + bool* isPainting) const OVERRIDE FINAL; + +private: + virtual void onGroupCreationFinished(const boost::shared_ptr& node,bool requestedByLoad,bool userEdited) OVERRIDE FINAL; virtual void createNodeGui(const boost::shared_ptr &node, diff --git a/Gui/GuiAppWrapper.h b/Gui/GuiAppWrapper.h index 206231da31..56c089f0f0 100644 --- a/Gui/GuiAppWrapper.h +++ b/Gui/GuiAppWrapper.h @@ -16,26 +16,24 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef GUIAPPWRAPPER_H #define GUIAPPWRAPPER_H +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + +#include "Global/Macros.h" + #include "Engine/AppInstanceWrapper.h" #include "Engine/ParameterWrapper.h" // ColorTuple +#include "Engine/EngineFwd.h" #include "Gui/GuiAppInstance.h" +#include "Gui/GuiFwd.h" -class PyModalDialog; -class PyPanel; -class PyTabWidget; -class QWidget; -class Effect; -class Group; -class ViewerTab; - -namespace Natron { -class Node; -} class PyViewer { diff --git a/Gui/GuiApplicationManager.h b/Gui/GuiApplicationManager.h index 72d4c4a1f4..eeb9b6cb52 100644 --- a/Gui/GuiApplicationManager.h +++ b/Gui/GuiApplicationManager.h @@ -16,21 +16,25 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef Gui_GuiApplicationManager_h #define Gui_GuiApplicationManager_h - // ***** BEGIN PYTHON BLOCK ***** // from : // "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include "Engine/AppManager.h" #include "Engine/Variant.h" +#include "Engine/EngineFwd.h" + +#include "Gui/GuiFwd.h" + #if defined(appPTR) #undef appPTR @@ -55,22 +59,7 @@ **/ #define getKeybind(group,action) ( appPTR->getKeySequenceForAction(group,action) ) -class QPixmap; -class QCursor; - -class ActionWithShortcut; -class PluginGroupNode; -class DockablePanel; -class KnobI; -class KnobGui; -class KnobSerialization; -class Curve; -class BoundAction; -class KeyBoundAction; -class QAction; -class NodeSerialization; -class NodeGuiSerialization; -struct NodeClipBoard; + struct PythonUserCommand { QString grouping; diff --git a/Gui/GuiApplicationManager10.cpp b/Gui/GuiApplicationManager10.cpp index 7ecf5297b9..1b96c50c63 100644 --- a/Gui/GuiApplicationManager10.cpp +++ b/Gui/GuiApplicationManager10.cpp @@ -251,6 +251,7 @@ bool Application::event(QEvent* e) { switch ( e->type() ) { +#if defined(Q_OS_MAC) || defined(Q_OS_SYMBIAN) case QEvent::FileOpen: { // This class is currently supported for Mac OS X and Symbian only // http://doc.qt.io/qt-4.8/qfileopenevent.html @@ -276,11 +277,11 @@ Application::event(QEvent* e) #endif _app->setFileToOpen(file); } + return true; } +#endif - return true; default: - return QApplication::event(e); } } diff --git a/Gui/GuiApplicationManagerPrivate.h b/Gui/GuiApplicationManagerPrivate.h index 467151f3a1..778c7ed87e 100644 --- a/Gui/GuiApplicationManagerPrivate.h +++ b/Gui/GuiApplicationManagerPrivate.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include #include @@ -34,11 +36,9 @@ #include #endif -#include - -#include "Global/Macros.h" CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) +#include #include #include CLANG_DIAG_ON(deprecated) @@ -46,15 +46,13 @@ CLANG_DIAG_ON(uninitialized) #include "Engine/Variant.h" #include "Engine/CLArgs.h" +#include "Engine/EngineFwd.h" #include "Gui/ActionShortcuts.h" // AppShortcuts #include "Gui/GuiApplicationManager.h" // PythonUserCommand #include "Gui/NodeClipBoard.h" +#include "Gui/GuiFwd.h" -class PluginGroupNode; -class KnobGuiFactory; -class Curve; -class SplashScreen; struct KnobsClipBoard { diff --git a/Gui/GuiDefines.h b/Gui/GuiDefines.h index 1b8f296b56..677023690e 100644 --- a/Gui/GuiDefines.h +++ b/Gui/GuiDefines.h @@ -25,6 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + +#include "Gui/GuiFwd.h" + + #define NATRON_BUTTON_BORDER 4 #define NATRON_SMALL_BUTTON_SIZE 15 #define NATRON_SMALL_BUTTON_ICON_SIZE (NATRON_SMALL_BUTTON_SIZE - NATRON_BUTTON_BORDER) diff --git a/Gui/GuiFwd.h b/Gui/GuiFwd.h new file mode 100644 index 0000000000..4b7cb1274e --- /dev/null +++ b/Gui/GuiFwd.h @@ -0,0 +1,194 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * This file is part of Natron , + * Copyright (C) 2015 INRIA and Alexandre Gauthier-Foichat + * + * Natron is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Natron is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Natron. If not, see + * ***** END LICENSE BLOCK ***** */ + +#ifndef Natron_Gui_GuiFwd_h +#define Natron_Gui_GuiFwd_h + +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." +#include +// ***** END PYTHON BLOCK ***** + +#include "Global/Macros.h" + +#include "Engine/EngineFwd.h" + +// Qt + +class QAbstractButton; +class QAction; +class QCheckBox; +class QColor; +class QCursor; +class QDialogButtonBox; +class QDragEnterEvent; +class QDragLeaveEvent; +class QDragMoveEvent; +class QDropEvent; +class QEvent; +class QFileSystemModel; +class QFileSystemWatcher; +class QFont; +class QFontComboBox; +class QFrame; +class QGLShaderProgram; +class QGraphicsLineItem; +class QGraphicsPolygonItem; +class QGraphicsScene; +class QGraphicsSceneMouseEvent; +class QGraphicsSimpleTextItem; +class QGraphicsTextItem; +class QGridLayout; +class QHBoxLayout; +class QIcon; +class QInputEvent; +class QItemSelection; +class QKeyEvent; +class QLinearGradient; +class QListView; +class QMenu; +class QMenuBar; +class QModelIndex; +class QMouseEvent; +class QMutex; +class QPaintEvent; +class QPainterPath; +class QPixmap; +class QPoint; +class QPointF; +class QProgressDialog; +class QRectF; +class QScrollArea; +class QSplitter; +class QStyleOptionViewItem; +class QTabWidget; +class QTextBrowser; +class QToolBar; +class QToolButton; +class QTreeWidget; +class QTreeWidgetItem; +class QUndoCommand; +class QUndoGroup; +class QUndoStack; +class QVBoxLayout; +class QWidget; + + +// Natron Gui + +class AboutWindow; +class ActionWithShortcut; +class AnimatedCheckBox; +class AnimationButton; +class BoundAction; +class Button; +class ChannelsComboBox; +class ComboBox; +class CurveEditor; +class CurveGui; +class CurveSelection; +class CurveWidget; +class DSKnob; +class DSNode; +class DockablePanel; +class DopeSheet; +class DopeSheetEditor; +class DopeSheetKey; +class DopeSheetView; +class DroppedTreeItem; +class Edge; +class FileDialogPreviewProvider; +class FloatingWidget; +class Histogram; +class Gui; +class GuiApp; +class GuiAppInstance; +class GuiLayoutSerialization; +class HierarchyView; +class Histogram; +class HostOverlay; +class InfoViewerWidget; +class KeyBoundAction; +class KnobCurveGui; +class KnobGui; +class KnobGuiFactory; +class KnobHolder; +class LineEdit; +class LinkArrow; +class MenuWithToolTips; +class MultiInstancePanel; +class NodeBackDropSerialization; +class NodeClipBoard; +class NodeCollection; +class NodeCurveEditorElement; +class NodeGraph; +class NodeGraphPixmapItem; +class NodeGraphTextItem; +class NodeGui; +class NodeGuiSerialization; +class NodeSerialization; +class NodeSettingsPanel; +class PanelWidget; +class PreferencesPanel; +class ProjectGui; +class ProjectGuiSerialization; +class PropertiesBinWrapper; +class PyModalDialog; +class PyPanel; +class PyTabWidget; +class RectI; +class RenderStatsDialog; +class RotoGui; +class RotoGuiSharedData; +class RotoPanel; +class ScaleSliderQWidget; +class ScriptEditor; +class ScriptObject; +class SequenceFileDialog; +class SequenceItemDelegate; +class ShortCutEditor; +class SpinBox; +class SpinBoxValidator; +class SplashScreen; +class Splitter; +class TabGroup; +class TabWidget; +class TableItem; +class TableModel; +class TableView; +class Texture; +class TimeLineGui; +class ToolButton; +class TrackerGui; +class TrackerPanel; +class VerticalColorBar; +class ViewerGL; +class ViewerTab; + +namespace Natron { +class ClickableLabel; +class GroupBoxLabel; +class Label; +class Menu; +//Implementation in Gui/QtMac.mm +bool isHighDPIInternal(const QWidget* w); +} + + +#endif // Natron_Gui_GuiFwd_h diff --git a/Gui/GuiMacros.h b/Gui/GuiMacros.h index 4b0b8cf2ae..3446073260 100644 --- a/Gui/GuiMacros.h +++ b/Gui/GuiMacros.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + // Mac keyboard: // ctrl = MetaModifier // alt = AltModifier diff --git a/Gui/GuiPrivate.cpp b/Gui/GuiPrivate.cpp index 3f837affca..74ecd3573c 100644 --- a/Gui/GuiPrivate.cpp +++ b/Gui/GuiPrivate.cpp @@ -565,14 +565,21 @@ bool GuiPrivate::checkProjectLockAndWarn(const QString& projectPath,const QString& projectName) { boost::shared_ptr project= _appInstance->getProject(); - QString author,lockCreationDate; + QString author; + QString lockCreationDate; + QString lockHost; qint64 lockPID; - if (project->getLockFileInfos(projectPath,projectName,&author, &lockCreationDate, &lockPID)) { + if (project->getLockFileInfos(projectPath, projectName, &author, &lockCreationDate, &lockHost, &lockPID)) { if (lockPID != QCoreApplication::applicationPid()) { Natron::StandardButtonEnum rep = Natron::questionDialog(QObject::tr("Project").toStdString(), - QObject::tr("This project is already opened in another instance of Natron by ").toStdString() + - author.toStdString() + QObject::tr(" and was opened on ").toStdString() + lockCreationDate.toStdString() - + QObject::tr(" by a Natron process ID of ").toStdString() + QString::number(lockPID).toStdString() + QObject::tr(".\nContinue anyway?").toStdString(), false, Natron::StandardButtons(Natron::eStandardButtonYes | Natron::eStandardButtonNo)); + QObject::tr("This project may be open in another instance of Natron " + "running on %1 as process ID %2, " + "and was opened by %3 on %4.\nContinue anyway?").arg(lockHost, + QString::number(lockPID), + author, + lockCreationDate).toStdString(), + false, + Natron::StandardButtons(Natron::eStandardButtonYes | Natron::eStandardButtonNo)); if (rep == Natron::eStandardButtonYes) { return true; } else { diff --git a/Gui/GuiPrivate.h b/Gui/GuiPrivate.h index 6b9e201084..dc3425bf74 100644 --- a/Gui/GuiPrivate.h +++ b/Gui/GuiPrivate.h @@ -25,12 +25,12 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include #include -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -44,46 +44,8 @@ CLANG_DIAG_ON(uninitialized) #include "Gui/GuiDefines.h" #include "Gui/RegisteredTabs.h" +#include "Gui/GuiFwd.h" -class QAction; -class QEvent; -class QHBoxLayout; -class QVBoxLayout; -class QMenuBar; -class QProgressDialog; -class QScrollArea; -class QUndoGroup; -class QUndoStack; -class QWidget; -class QToolButton; - -class AboutWindow; -class ActionWithShortcut; -class Button; -class CurveEditor; -class DopeSheetEditor; -class FloatingWidget; -class Histogram; -class Gui; -class GuiAppInstance; -namespace Natron { - class Menu; -} -class NodeGraph; -class PreferencesPanel; -class ProjectGui; -class PropertiesBinWrapper; -class PyPanel; -class ShortCutEditor; -class SpinBox; -class Splitter; -class TabWidget; -class ToolButton; -class ViewerTab; -class KnobHolder; -class DockablePanel; -class ScriptEditor; -class RenderStatsDialog; #define kPropertiesBinName "properties" diff --git a/Gui/Histogram.h b/Gui/Histogram.h index debcbf00d4..672d301399 100644 --- a/Gui/Histogram.h +++ b/Gui/Histogram.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef HISTOGRAM_H #define HISTOGRAM_H @@ -26,25 +25,25 @@ #include // ***** END PYTHON BLOCK ***** -#include "Global/GLIncludes.h" //! +#include +#endif + +#include "Global/GLIncludes.h" //! CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) -#include -#include -#endif + #include "Gui/PanelWidget.h" +#include "Gui/GuiFwd.h" -class QString; -class QColor; -class QFont; -class Gui; -class ViewerGL; /** * @class An histogram view in the histograms gui. **/ diff --git a/Gui/HostOverlay.h b/Gui/HostOverlay.h index 864b5744fb..af7755c6b5 100644 --- a/Gui/HostOverlay.h +++ b/Gui/HostOverlay.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef Gui_HostOverlay_h #define Gui_HostOverlay_h @@ -26,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include @@ -33,17 +34,16 @@ #endif #include "Global/GlobalDefines.h" + #include "Engine/OfxOverlayInteract.h" -class KnobDouble; -class KnobChoice; -class KnobBool; -class KnobI; -class QPoint; -class QPointF; -class NodeGui; +#include "Gui/GuiFwd.h" + + +// defined below: struct PositionInteract; struct HostOverlayPrivate; + class HostOverlay : public Natron::NatronOverlayInteractSupport { diff --git a/Gui/InfoViewerWidget.h b/Gui/InfoViewerWidget.h index adb5391f44..48f1949d37 100644 --- a/Gui/InfoViewerWidget.h +++ b/Gui/InfoViewerWidget.h @@ -26,6 +26,7 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -37,11 +38,8 @@ CLANG_DIAG_ON(uninitialized) #include "Engine/Format.h" #include "Engine/ImageComponents.h" -class ViewerGL; -namespace Natron { - class Label; -} -class QHBoxLayout; +#include "Gui/GuiFwd.h" + class InfoViewerWidget : public QWidget diff --git a/Gui/KnobGui.cpp b/Gui/KnobGui.cpp index 0461e6173a..680367571c 100644 --- a/Gui/KnobGui.cpp +++ b/Gui/KnobGui.cpp @@ -22,16 +22,19 @@ #include // ***** END PYTHON BLOCK ***** -#include "Gui/KnobGui.h" -#include "Gui/KnobGuiPrivate.h" - #include - #include +#include "Engine/KnobTypes.h" + +#include "Gui/KnobGui.h" +#include "Gui/KnobGuiPrivate.h" #include "Gui/GuiDefines.h" #include "Gui/ClickableLabel.h" + + + using namespace Natron; @@ -623,7 +626,11 @@ KnobGui::createAnimationMenu(QMenu* menu,int dimension) } // createAnimationMenu boost::shared_ptr -KnobGui::createDuplicateOnNode(Natron::EffectInstance* effect,bool makeAlias) +KnobGui::createDuplicateOnNode(Natron::EffectInstance* effect, + bool makeAlias, + const boost::shared_ptr& page, + const boost::shared_ptr& group, + int indexInParent) { ///find-out to which node that master knob belongs to assert( getKnob()->getHolder()->getApp() ); @@ -645,7 +652,27 @@ KnobGui::createDuplicateOnNode(Natron::EffectInstance* effect,bool makeAlias) } } - boost::shared_ptr ret = knob->createDuplicateOnNode(effect,makeAlias); + Natron::EffectInstance* isEffect = dynamic_cast(knob->getHolder()); + if (!isEffect) { + return boost::shared_ptr(); + } + const std::string& nodeScriptName = isEffect->getNode()->getScriptName(); + std::string newKnobName = nodeScriptName + knob->getName(); + boost::shared_ptr ret; + try { + ret = knob->createDuplicateOnNode(effect, + page, + group, + indexInParent, + makeAlias, + newKnobName, + knob->getLabel(), + knob->getHintToolTip(), + true); + } catch (const std::exception& e) { + Natron::errorDialog(tr("Error while creating parameter").toStdString(), e.what()); + return boost::shared_ptr(); + } if (ret) { boost::shared_ptr groupNodeGuiI = effect->getNode()->getNodeGui(); NodeGui* groupNodeGui = dynamic_cast(groupNodeGuiI.get()); diff --git a/Gui/KnobGui.h b/Gui/KnobGui.h index 6f664e4e7e..c33dd2cd74 100644 --- a/Gui/KnobGui.h +++ b/Gui/KnobGui.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // DBL_MAX #include // INT_MAX @@ -33,8 +35,6 @@ #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -46,31 +46,10 @@ CLANG_DIAG_ON(uninitialized) #include "Engine/Knob.h" #include "Engine/Curve.h" #include "Engine/KnobGuiI.h" +#include "Engine/EngineFwd.h" + +#include "Gui/GuiFwd.h" -// Qt -class QUndoCommand; //used by KnobGui -class QVBoxLayout; //used by KnobGui -class QHBoxLayout; //used by KnobGui -class QGridLayout; -class QMenu; -namespace Natron { -class ClickableLabel; -class Label; -class EffectInstance; -} -class QString; - -// Engine -class Variant; //used by KnobGui -class KeyFrame; - -// Gui -class ComboBox; -class Button; -class AnimationButton; //used by KnobGui -class DockablePanel; //used by KnobGui -class Gui; -class NodeGui; #define SLIDER_MAX_RANGE 100000 @@ -247,8 +226,6 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON ///Should set to the underlying knob the gui ptr virtual void setKnobGuiPointer() OVERRIDE FINAL; - virtual void onKnobDeletion() OVERRIDE FINAL; - virtual bool isGuiFrozenForPlayback() const OVERRIDE FINAL; virtual void copyAnimationToClipboard() const OVERRIDE FINAL; @@ -264,7 +241,11 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON **/ bool isSecretRecursive() const; - boost::shared_ptr createDuplicateOnNode(Natron::EffectInstance* effect,bool makeAlias); + boost::shared_ptr createDuplicateOnNode(Natron::EffectInstance* effect, + bool makeAlias, + const boost::shared_ptr& page, + const boost::shared_ptr& group, + int indexInParent); static bool shouldSliderBeVisible(int sliderMin, int sliderMax) diff --git a/Gui/KnobGui10.cpp b/Gui/KnobGui10.cpp index 3511ace318..2684c319d2 100644 --- a/Gui/KnobGui10.cpp +++ b/Gui/KnobGui10.cpp @@ -23,6 +23,7 @@ // ***** END PYTHON BLOCK ***** #include "Engine/Knob.h" +#include "Engine/KnobTypes.h" #include "Gui/KnobGui.h" #include "Gui/KnobGuiPrivate.h" @@ -47,7 +48,7 @@ KnobGui::onCreateAliasOnGroupActionTriggered() NodeGroup* isCollecGroup = dynamic_cast(collec.get()); assert(isCollecGroup); if (isCollecGroup) { - createDuplicateOnNode(isCollecGroup, true); + createDuplicateOnNode(isCollecGroup, true, boost::shared_ptr(), boost::shared_ptr(), -1); } } diff --git a/Gui/KnobGui20.cpp b/Gui/KnobGui20.cpp index 2c5158298c..d6d17cfbbe 100644 --- a/Gui/KnobGui20.cpp +++ b/Gui/KnobGui20.cpp @@ -747,12 +747,6 @@ KnobGui::onHelpChanged() updateToolTip(); } -void -KnobGui::onKnobDeletion() -{ - _imp->container->deleteKnobGui(getKnob()); -} - void KnobGui::onHasModificationsChanged() diff --git a/Gui/KnobGuiBool.cpp b/Gui/KnobGuiBool.cpp index 28f07bdf65..64825f6d9d 100644 --- a/Gui/KnobGuiBool.cpp +++ b/Gui/KnobGuiBool.cpp @@ -191,6 +191,9 @@ KnobGuiBool::onLabelChangedInternal() void KnobGuiBool::onLabelClicked(bool b) { + if (_checkBox->getReadOnly()) { + return; + } _checkBox->setChecked(b); pushUndoCommand( new KnobUndoCommand(this,_knob.lock()->getValue(0),b, 0, false) ); } @@ -220,14 +223,14 @@ KnobGuiBool::setEnabled() bool b = knob->isEnabled(0) && knob->getExpression(0).empty(); - _checkBox->setEnabled(b); + _checkBox->setReadOnly(!b); } void KnobGuiBool::setReadOnly(bool readOnly, int /*dimension*/) { - _checkBox->setEnabled(!readOnly); + _checkBox->setReadOnly(readOnly); } void @@ -248,7 +251,7 @@ KnobGuiBool::reflectExpressionState(int /*dimension*/, { bool isEnabled = _knob.lock()->isEnabled(0); _checkBox->setAnimation(3); - _checkBox->setEnabled(!hasExpr && isEnabled); + _checkBox->setReadOnly(hasExpr || !isEnabled); } void diff --git a/Gui/KnobGuiBool.h b/Gui/KnobGuiBool.h index d54c75f1f1..512d99eead 100644 --- a/Gui/KnobGuiBool.h +++ b/Gui/KnobGuiBool.h @@ -25,9 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // KnobGuiInt #include -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -36,61 +38,19 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" #include "Global/GlobalDefines.h" #include "Engine/Singleton.h" #include "Engine/Knob.h" #include "Engine/ImageComponents.h" +#include "Engine/EngineFwd.h" #include "Gui/CurveSelection.h" #include "Gui/KnobGui.h" #include "Gui/AnimatedCheckBox.h" #include "Gui/Label.h" +#include "Gui/GuiFwd.h" -// Qt -class QString; -class QFrame; -class QHBoxLayout; -class QTreeWidget; -class QTreeWidgetItem; -class QScrollArea; -class QFontComboBox; - -// Engine -class KnobI; -class KnobInt; -class KnobBool; -class KnobDouble; -class KnobButton; -class KnobSeparator; -class KnobGroup; -class KnobParametric; -class KnobColor; -class KnobChoice; -class KnobString; - -// Gui -class DockablePanel; -class LineEdit; -class Button; -class SpinBox; -class ComboBox; -class ScaleSliderQWidget; -class CurveWidget; -class KnobCurveGui; -class TabGroup; - -// private classes, defined in KnobGuiTypes.cpp -namespace Natron { -class GroupBoxLabel; -class ClickableLabel; -} -class AnimatedCheckBox; - -namespace Natron { -class Node; -} //================================ diff --git a/Gui/KnobGuiButton.h b/Gui/KnobGuiButton.h index b634bcb0ee..55ea7522b7 100644 --- a/Gui/KnobGuiButton.h +++ b/Gui/KnobGuiButton.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // KnobGuiInt #include #include "Global/Macros.h" @@ -36,61 +38,19 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" #include "Global/GlobalDefines.h" #include "Engine/Singleton.h" #include "Engine/Knob.h" #include "Engine/ImageComponents.h" +#include "Engine/EngineFwd.h" #include "Gui/CurveSelection.h" #include "Gui/KnobGui.h" #include "Gui/AnimatedCheckBox.h" #include "Gui/Label.h" +#include "Gui/GuiFwd.h" -// Qt -class QString; -class QFrame; -class QHBoxLayout; -class QTreeWidget; -class QTreeWidgetItem; -class QScrollArea; -class QFontComboBox; - -// Engine -class KnobI; -class KnobInt; -class KnobBool; -class KnobDouble; -class KnobButton; -class KnobSeparator; -class KnobGroup; -class KnobParametric; -class KnobColor; -class KnobChoice; -class KnobString; - -// Gui -class DockablePanel; -class LineEdit; -class Button; -class SpinBox; -class ComboBox; -class ScaleSliderQWidget; -class CurveWidget; -class KnobCurveGui; -class TabGroup; - -// private classes, defined in KnobGuiTypes.cpp -namespace Natron { -class GroupBoxLabel; -class ClickableLabel; -} -class AnimatedCheckBox; - -namespace Natron { -class Node; -} //================================ class KnobGuiButton diff --git a/Gui/KnobGuiChoice.h b/Gui/KnobGuiChoice.h index 1d5d6033eb..cb2bf54d9c 100644 --- a/Gui/KnobGuiChoice.h +++ b/Gui/KnobGuiChoice.h @@ -25,9 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // KnobGuiInt #include -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -36,61 +38,19 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" #include "Global/GlobalDefines.h" #include "Engine/Singleton.h" #include "Engine/Knob.h" #include "Engine/ImageComponents.h" +#include "Engine/EngineFwd.h" #include "Gui/CurveSelection.h" #include "Gui/KnobGui.h" #include "Gui/AnimatedCheckBox.h" #include "Gui/Label.h" +#include "Gui/GuiFwd.h" -// Qt -class QString; -class QFrame; -class QHBoxLayout; -class QTreeWidget; -class QTreeWidgetItem; -class QScrollArea; -class QFontComboBox; - -// Engine -class KnobI; -class KnobInt; -class KnobBool; -class KnobDouble; -class KnobButton; -class KnobSeparator; -class KnobGroup; -class KnobParametric; -class KnobColor; -class KnobChoice; -class KnobString; - -// Gui -class DockablePanel; -class LineEdit; -class Button; -class SpinBox; -class ComboBox; -class ScaleSliderQWidget; -class CurveWidget; -class KnobCurveGui; -class TabGroup; - -// private classes, defined in KnobGuiTypes.cpp -namespace Natron { -class GroupBoxLabel; -class ClickableLabel; -} -class AnimatedCheckBox; - -namespace Natron { -class Node; -} class KnobGuiChoice : public KnobGui diff --git a/Gui/KnobGuiColor.cpp b/Gui/KnobGuiColor.cpp index eb1c96a425..297ca780ef 100644 --- a/Gui/KnobGuiColor.cpp +++ b/Gui/KnobGuiColor.cpp @@ -958,12 +958,18 @@ KnobGuiColor::onDialogCurrentColorChanged(const QColor & color) boost::shared_ptr knob = _knob.lock(); if (_dimension == 1) { knob->setValue(Natron::Color::from_func_srgb(color.redF()), 0); - } else if (_dimension >= 3) { + } else if (_dimension == 3) { ///Don't set alpha since the color dialog can only handle RGB knob->setValues(Natron::Color::from_func_srgb(color.redF()), Natron::Color::from_func_srgb(color.greenF()), Natron::Color::from_func_srgb(color.blueF()), Natron::eValueChangedReasonNatronInternalEdited); + } else if (_dimension == 4) { + knob->setValues(Natron::Color::from_func_srgb(color.redF()), + Natron::Color::from_func_srgb(color.greenF()), + Natron::Color::from_func_srgb(color.blueF()), + 1., + Natron::eValueChangedReasonNatronInternalEdited); } } @@ -992,6 +998,13 @@ KnobGuiColor::onColorChanged() if (isSpinbox) { _slider->seekScalePosition(r); } + if (_dimension >= 3) { + _gBox->setValue(g); + _bBox->setValue(b); + if (_dimension >= 4) { + _aBox->setValue(a); + } + } } if (_dimension >= 3) { newValues.push_back(g); diff --git a/Gui/KnobGuiColor.h b/Gui/KnobGuiColor.h index b43a562259..f6ea6a7186 100644 --- a/Gui/KnobGuiColor.h +++ b/Gui/KnobGuiColor.h @@ -25,9 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // KnobGuiInt #include -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -36,63 +38,20 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" #include "Global/GlobalDefines.h" #include "Engine/Singleton.h" #include "Engine/Knob.h" #include "Engine/ImageComponents.h" +#include "Engine/EngineFwd.h" #include "Gui/CurveSelection.h" #include "Gui/KnobGui.h" #include "Gui/AnimatedCheckBox.h" #include "Gui/Label.h" +#include "Gui/GuiFwd.h" -// Qt -class QString; -class QFrame; -class QHBoxLayout; -class QTreeWidget; -class QTreeWidgetItem; -class QScrollArea; -class QFontComboBox; - -// Engine -class KnobI; -class KnobInt; -class KnobBool; -class KnobDouble; -class KnobButton; -class KnobSeparator; -class KnobGroup; -class KnobParametric; -class KnobColor; -class KnobChoice; -class KnobString; - -// Gui -class DockablePanel; -class LineEdit; -class Button; -class SpinBox; -class ComboBox; -class ScaleSliderQWidget; -class CurveWidget; -class KnobCurveGui; -class TabGroup; - -// private classes, defined in KnobGuiTypes.cpp -namespace Natron { -class GroupBoxLabel; -class ClickableLabel; -} -class AnimatedCheckBox; - -namespace Natron { -class Node; -} - //================================ class KnobGuiColor; diff --git a/Gui/KnobGuiDouble.h b/Gui/KnobGuiDouble.h index 23f1174a1a..cb2bc982a4 100644 --- a/Gui/KnobGuiDouble.h +++ b/Gui/KnobGuiDouble.h @@ -25,9 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // KnobGuiInt #include -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -36,61 +38,19 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" #include "Global/GlobalDefines.h" #include "Engine/Singleton.h" #include "Engine/Knob.h" #include "Engine/ImageComponents.h" +#include "Engine/EngineFwd.h" #include "Gui/CurveSelection.h" #include "Gui/KnobGui.h" #include "Gui/AnimatedCheckBox.h" #include "Gui/Label.h" +#include "Gui/GuiFwd.h" -// Qt -class QString; -class QFrame; -class QHBoxLayout; -class QTreeWidget; -class QTreeWidgetItem; -class QScrollArea; -class QFontComboBox; - -// Engine -class KnobI; -class KnobInt; -class KnobBool; -class KnobDouble; -class KnobButton; -class KnobSeparator; -class KnobGroup; -class KnobParametric; -class KnobColor; -class KnobChoice; -class KnobString; - -// Gui -class DockablePanel; -class LineEdit; -class Button; -class SpinBox; -class ComboBox; -class ScaleSliderQWidget; -class CurveWidget; -class KnobCurveGui; -class TabGroup; - -// private classes, defined in KnobGuiTypes.cpp -namespace Natron { -class GroupBoxLabel; -class ClickableLabel; -} -class AnimatedCheckBox; - -namespace Natron { -class Node; -} class KnobGuiDouble : public KnobGui diff --git a/Gui/KnobGuiFactory.h b/Gui/KnobGuiFactory.h index 71f95e6814..01ed63fa08 100644 --- a/Gui/KnobGuiFactory.h +++ b/Gui/KnobGuiFactory.h @@ -25,17 +25,17 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif -class KnobI; -class DockablePanel; -namespace Natron { -class LibraryBinary; -} +#include "Gui/GuiFwd.h" + /******************************KNOB_FACTORY**************************************/ //Maybe the factory should move to a separate file since it is used to create KnobGui aswell diff --git a/Gui/KnobGuiFile.h b/Gui/KnobGuiFile.h index 5fbafa7fc9..2f1714213f 100644 --- a/Gui/KnobGuiFile.h +++ b/Gui/KnobGuiFile.h @@ -25,8 +25,10 @@ #include // ***** END PYTHON BLOCK ***** -#include #include "Global/Macros.h" + +#include + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -37,26 +39,9 @@ CLANG_DIAG_ON(uninitialized) #include "Global/GlobalDefines.h" #include "Gui/KnobGui.h" +#include "Gui/GuiFwd.h" + -// Qt -class QHBoxLayout; -class QMenu; -class QFileSystemWatcher; - -// Engine -class KnobI; -class KnobFile; -class KnobOutputFile; -class KnobPath; - -// Gui -class LineEdit; -class DockablePanel; -class Button; -class KnobFile_UndoCommand; -class TableView; -class TableModel; -class TableItem; //================================ class KnobGuiFile : public KnobGui @@ -65,8 +50,6 @@ GCC_DIAG_SUGGEST_OVERRIDE_OFF Q_OBJECT GCC_DIAG_SUGGEST_OVERRIDE_ON - friend class KnobFile_UndoCommand; - public: static KnobGui * BuildKnobGui(boost::shared_ptr knob, diff --git a/Gui/KnobGuiGroup.h b/Gui/KnobGuiGroup.h index 265c0e16e6..025eb7b5a0 100644 --- a/Gui/KnobGuiGroup.h +++ b/Gui/KnobGuiGroup.h @@ -25,9 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // KnobGuiInt #include -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -36,61 +38,18 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" #include "Global/GlobalDefines.h" #include "Engine/Singleton.h" #include "Engine/Knob.h" #include "Engine/ImageComponents.h" +#include "Engine/EngineFwd.h" #include "Gui/CurveSelection.h" #include "Gui/KnobGui.h" #include "Gui/AnimatedCheckBox.h" #include "Gui/Label.h" - -// Qt -class QString; -class QFrame; -class QHBoxLayout; -class QTreeWidget; -class QTreeWidgetItem; -class QScrollArea; -class QFontComboBox; - -// Engine -class KnobI; -class KnobInt; -class KnobBool; -class KnobDouble; -class KnobButton; -class KnobSeparator; -class KnobGroup; -class KnobParametric; -class KnobColor; -class KnobChoice; -class KnobString; - -// Gui -class DockablePanel; -class LineEdit; -class Button; -class SpinBox; -class ComboBox; -class ScaleSliderQWidget; -class CurveWidget; -class KnobCurveGui; -class TabGroup; - -// private classes, defined in KnobGuiTypes.cpp -namespace Natron { -class GroupBoxLabel; -class ClickableLabel; -} -class AnimatedCheckBox; - -namespace Natron { -class Node; -} +#include "Gui/GuiFwd.h" class KnobGuiGroup diff --git a/Gui/KnobGuiInt.h b/Gui/KnobGuiInt.h index 4c3c0bc4d8..95bc6b459b 100644 --- a/Gui/KnobGuiInt.h +++ b/Gui/KnobGuiInt.h @@ -25,9 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // KnobGuiInt #include -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -36,61 +38,19 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" #include "Global/GlobalDefines.h" #include "Engine/Singleton.h" #include "Engine/Knob.h" #include "Engine/ImageComponents.h" +#include "Engine/EngineFwd.h" #include "Gui/CurveSelection.h" #include "Gui/KnobGui.h" #include "Gui/AnimatedCheckBox.h" #include "Gui/Label.h" +#include "Gui/GuiFwd.h" -// Qt -class QString; -class QFrame; -class QHBoxLayout; -class QTreeWidget; -class QTreeWidgetItem; -class QScrollArea; -class QFontComboBox; - -// Engine -class KnobI; -class KnobInt; -class KnobBool; -class KnobDouble; -class KnobButton; -class KnobSeparator; -class KnobGroup; -class KnobParametric; -class KnobColor; -class KnobChoice; -class KnobString; - -// Gui -class DockablePanel; -class LineEdit; -class Button; -class SpinBox; -class ComboBox; -class ScaleSliderQWidget; -class CurveWidget; -class KnobCurveGui; -class TabGroup; - -// private classes, defined in KnobGuiTypes.cpp -namespace Natron { -class GroupBoxLabel; -class ClickableLabel; -} -class AnimatedCheckBox; - -namespace Natron { -class Node; -} //================================ diff --git a/Gui/KnobGuiParametric.cpp b/Gui/KnobGuiParametric.cpp index 311315ce0a..fc89122957 100644 --- a/Gui/KnobGuiParametric.cpp +++ b/Gui/KnobGuiParametric.cpp @@ -273,15 +273,17 @@ void KnobGuiParametric::resetSelectedCurves() { QList selected = _tree->selectedItems(); + boost::shared_ptr k = _knob.lock(); for (int i = 0; i < selected.size(); ++i) { //find the items in the curves for (CurveGuis::iterator it = _curves.begin(); it != _curves.end(); ++it) { if ( it->second.treeItem == selected.at(i) ) { - _knob.lock()->resetToDefaultValue(it->second.curve->getDimension()); + k->resetToDefaultValue(it->second.curve->getDimension()); break; } } } + k->evaluateValueChange(0, k->getCurrentTime(), Natron::eValueChangedReasonUserEdited); } boost::shared_ptr KnobGuiParametric::getKnob() const diff --git a/Gui/KnobGuiParametric.h b/Gui/KnobGuiParametric.h index 48c14e3f32..579060e7fa 100644 --- a/Gui/KnobGuiParametric.h +++ b/Gui/KnobGuiParametric.h @@ -25,9 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // KnobGuiInt #include -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -36,61 +38,19 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" #include "Global/GlobalDefines.h" #include "Engine/Singleton.h" #include "Engine/Knob.h" #include "Engine/ImageComponents.h" +#include "Engine/EngineFwd.h" #include "Gui/CurveSelection.h" #include "Gui/KnobGui.h" #include "Gui/AnimatedCheckBox.h" #include "Gui/Label.h" +#include "Gui/GuiFwd.h" -// Qt -class QString; -class QFrame; -class QHBoxLayout; -class QTreeWidget; -class QTreeWidgetItem; -class QScrollArea; -class QFontComboBox; - -// Engine -class KnobI; -class KnobInt; -class KnobBool; -class KnobDouble; -class KnobButton; -class KnobSeparator; -class KnobGroup; -class KnobParametric; -class KnobColor; -class KnobChoice; -class KnobString; - -// Gui -class DockablePanel; -class LineEdit; -class Button; -class SpinBox; -class ComboBox; -class ScaleSliderQWidget; -class CurveWidget; -class KnobCurveGui; -class TabGroup; - -// private classes, defined in KnobGuiTypes.cpp -namespace Natron { -class GroupBoxLabel; -class ClickableLabel; -} -class AnimatedCheckBox; - -namespace Natron { -class Node; -} class KnobGuiParametric : public KnobGui diff --git a/Gui/KnobGuiSeparator.h b/Gui/KnobGuiSeparator.h index 8c141eeab2..429534b3da 100644 --- a/Gui/KnobGuiSeparator.h +++ b/Gui/KnobGuiSeparator.h @@ -25,9 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // KnobGuiInt #include -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -36,61 +38,19 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" #include "Global/GlobalDefines.h" #include "Engine/Singleton.h" #include "Engine/Knob.h" #include "Engine/ImageComponents.h" +#include "Engine/EngineFwd.h" #include "Gui/CurveSelection.h" #include "Gui/KnobGui.h" #include "Gui/AnimatedCheckBox.h" #include "Gui/Label.h" +#include "Gui/GuiFwd.h" -// Qt -class QString; -class QFrame; -class QHBoxLayout; -class QTreeWidget; -class QTreeWidgetItem; -class QScrollArea; -class QFontComboBox; - -// Engine -class KnobI; -class KnobInt; -class KnobBool; -class KnobDouble; -class KnobButton; -class KnobSeparator; -class KnobGroup; -class KnobParametric; -class KnobColor; -class KnobChoice; -class KnobString; - -// Gui -class DockablePanel; -class LineEdit; -class Button; -class SpinBox; -class ComboBox; -class ScaleSliderQWidget; -class CurveWidget; -class KnobCurveGui; -class TabGroup; - -// private classes, defined in KnobGuiTypes.cpp -namespace Natron { -class GroupBoxLabel; -class ClickableLabel; -} -class AnimatedCheckBox; - -namespace Natron { -class Node; -} class KnobGuiSeparator : public KnobGui diff --git a/Gui/KnobGuiString.h b/Gui/KnobGuiString.h index a64b33bf16..9f3136525b 100644 --- a/Gui/KnobGuiString.h +++ b/Gui/KnobGuiString.h @@ -25,9 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // KnobGuiInt #include -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -36,61 +38,18 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" #include "Global/GlobalDefines.h" #include "Engine/Singleton.h" #include "Engine/Knob.h" #include "Engine/ImageComponents.h" +#include "Engine/EngineFwd.h" #include "Gui/CurveSelection.h" #include "Gui/KnobGui.h" #include "Gui/AnimatedCheckBox.h" #include "Gui/Label.h" - -// Qt -class QString; -class QFrame; -class QHBoxLayout; -class QTreeWidget; -class QTreeWidgetItem; -class QScrollArea; -class QFontComboBox; - -// Engine -class KnobI; -class KnobInt; -class KnobBool; -class KnobDouble; -class KnobButton; -class KnobSeparator; -class KnobGroup; -class KnobParametric; -class KnobColor; -class KnobChoice; -class KnobString; - -// Gui -class DockablePanel; -class LineEdit; -class Button; -class SpinBox; -class ComboBox; -class ScaleSliderQWidget; -class CurveWidget; -class KnobCurveGui; -class TabGroup; - -// private classes, defined in KnobGuiTypes.cpp -namespace Natron { -class GroupBoxLabel; -class ClickableLabel; -} -class AnimatedCheckBox; - -namespace Natron { -class Node; -} +#include "Gui/GuiFwd.h" class AnimatingTextEdit diff --git a/Gui/KnobUndoCommand.h b/Gui/KnobUndoCommand.h index 2bf485fcef..b41bf4ed6c 100644 --- a/Gui/KnobUndoCommand.h +++ b/Gui/KnobUndoCommand.h @@ -25,10 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include -#include "Global/Macros.h" CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -49,6 +50,7 @@ CLANG_DIAG_ON(uninitialized) #include "Gui/CurveEditor.h" #include "Gui/CurveWidget.h" #include "Gui/GuiAppInstance.h" +#include "Gui/GuiFwd.h" //================================================================ @@ -112,13 +114,31 @@ class KnobUndoCommand bool modifiedKeyFrame = false; int i = 0; - _knob->getKnob()->beginChanges(); + boost::shared_ptr knob = _knob->getKnob(); + knob->beginChanges(); + + assert((int)_oldValue.size() == _knob->getKnob()->getDimension() || _dimension != -1); + + typename std::list::iterator next = _oldValue.end(); + if (next != _oldValue.end()) { + ++next; + } for (typename std::list::iterator it = _oldValue.begin(); it != _oldValue.end(); ++it) { int dimension = _dimension == -1 ? i : _dimension; + if (it == _oldValue.begin() && _oldValue.size() > 1) { + knob->blockValueChanges(); + } + + if (next == _oldValue.end() && _oldValue.size() > 1) { + knob->unblockValueChanges(); + } + + _knob->setValue(dimension,*it,NULL,false,Natron::eValueChangedReasonUserEdited); - if ( _knob->getKnob()->getHolder()->getApp() ) { + + if (knob->getHolder()->getApp() ) { if (_valueChangedReturnCode[i] == 1) { //the value change also added a keyframe _knob->removeKeyFrame(_newKeys[i].getTime(),dimension); modifiedKeyFrame = true; @@ -130,7 +150,9 @@ class KnobUndoCommand } } - + if (next != _oldValue.end()) { + ++next; + } ++i; } @@ -138,7 +160,7 @@ class KnobUndoCommand ///This will refresh all dimensions _knob->onInternalValueChanged(-1, Natron::eValueChangedReasonNatronGuiEdited); - _knob->getKnob()->endChanges(); + knob->endChanges(); if (modifiedKeyFrame) { _knob->getGui()->getCurveEditor()->getCurveWidget()->refreshSelectedKeys(); } @@ -156,15 +178,23 @@ class KnobUndoCommand time = knob->getHolder()->getApp()->getTimeLine()->currentFrame(); } + assert((int)_oldValue.size() == _knob->getKnob()->getDimension() || _dimension != -1); + bool modifiedKeyFrames = false; knob->beginChanges(); int i = 0; - + typename std::list::iterator next = _newValue.end(); + if (next != _newValue.end()) { + ++next; + } for (typename std::list::iterator it = _newValue.begin(); it != _newValue.end(); ++it) { int dimension = _dimension == -1 ? i : _dimension; - + if (it == _newValue.begin() && _newValue.size() > 1) { + knob->blockValueChanges(); + } + boost::shared_ptr c = knob->getCurve(dimension); //find out if there's already an existing keyframe before calling setValue if (c) { @@ -172,7 +202,10 @@ class KnobUndoCommand Q_UNUSED(found); // we don't care if it existed or not } - + if (next == _newValue.end() && _newValue.size() > 1) { + knob->unblockValueChanges(); + } + _valueChangedReturnCode[i] = _knob->setValue(dimension,*it,&_newKeys[i],false,Natron::eValueChangedReasonUserEdited); if (_valueChangedReturnCode[i] != KnobHelper::eValueChangedReturnCodeNoKeyframeAdded) { modifiedKeyFrames = true; @@ -183,6 +216,9 @@ class KnobUndoCommand _merge = false; } ++i; + if (next != _newValue.end()) { + ++next; + } } diff --git a/Gui/Label.h b/Gui/Label.h index c2d2d2e32a..f171bd5b30 100644 --- a/Gui/Label.h +++ b/Gui/Label.h @@ -26,6 +26,7 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -33,7 +34,7 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" +#include "Gui/GuiFwd.h" namespace Natron { diff --git a/Gui/LineEdit.h b/Gui/LineEdit.h index 1407c7b472..173c33b700 100644 --- a/Gui/LineEdit.h +++ b/Gui/LineEdit.h @@ -26,19 +26,15 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" +#include "Gui/GuiFwd.h" -class QPaintEvent; -class QDropEvent; -class QDragEnterEvent; -class QDragMoveEvent; -class QDragLeaveEvent; class LineEdit : public QLineEdit diff --git a/Gui/LinkToKnobDialog.cpp b/Gui/LinkToKnobDialog.cpp index 6d23719d81..f01667da5f 100644 --- a/Gui/LinkToKnobDialog.cpp +++ b/Gui/LinkToKnobDialog.cpp @@ -209,7 +209,7 @@ LinkToKnobDialog::onNodeComboEditingFinished() KnobPage* isPage = dynamic_cast( knobs[j].get() ); KnobGroup* isGroup = dynamic_cast( knobs[j].get() ); if (from->isTypeCompatible(knobs[j]) && !isButton && !isPage && !isGroup) { - QString name( knobs[j]->getLabel().c_str() ); + QString name( knobs[j]->getName().c_str() ); bool canInsertKnob = true; for (int k = 0; k < knobs[j]->getDimension(); ++k) { diff --git a/Gui/LinkToKnobDialog.h b/Gui/LinkToKnobDialog.h index c6b22d8b19..81b3c1dcf3 100644 --- a/Gui/LinkToKnobDialog.h +++ b/Gui/LinkToKnobDialog.h @@ -25,11 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include -#include "Global/Macros.h" - #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include @@ -43,11 +43,8 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -class QStringList; +#include "Gui/GuiFwd.h" -class QWidget; -class KnobGui; -class KnobI; struct LinkToKnobDialogPrivate; diff --git a/Gui/LogWindow.h b/Gui/LogWindow.h index 49a6f96847..bf39c43037 100644 --- a/Gui/LogWindow.h +++ b/Gui/LogWindow.h @@ -33,10 +33,8 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -class QVBoxLayout; -class QTextBrowser; -class Button; -class QString; +#include "Gui/GuiFwd.h" + class LogWindow : public QDialog diff --git a/Gui/ManageUserParamsDialog.cpp b/Gui/ManageUserParamsDialog.cpp index 66e9ba2585..6c0611e127 100644 --- a/Gui/ManageUserParamsDialog.cpp +++ b/Gui/ManageUserParamsDialog.cpp @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "Engine/Knob.h" // KnobI #include "Engine/KnobTypes.h" // KnobPage @@ -54,15 +56,32 @@ struct TreeItem { QTreeWidgetItem* item; boost::shared_ptr knob; + QString scriptName; }; } +class UserParamsDialogTreeWidget : public QTreeWidget +{ +public: + + UserParamsDialogTreeWidget(QWidget* parent) + : QTreeWidget(parent) + { + + } + + QModelIndex indexFromItemPublic(QTreeWidgetItem *item, int column = 0) const + { + return indexFromItem(item,column); + } +}; + struct ManageUserParamsDialogPrivate { DockablePanel* panel; QHBoxLayout* mainLayout; - QTreeWidget* tree; + UserParamsDialogTreeWidget* tree; std::list items; @@ -97,22 +116,43 @@ struct ManageUserParamsDialogPrivate } - boost::shared_ptr getUserPageKnob() const; void initializeKnobs(const std::vector >& knobs,QTreeWidgetItem* parent,std::list& markedKnobs); void rebuildUserPages(); - void onKnobAddedInternal(const boost::shared_ptr& knob); + QTreeWidgetItem* createItemForKnob(const boost::shared_ptr& knob,int insertIndex = -1); + + bool createUserPageItem(); + + void saveAndRebuildPages(); + + std::list::const_iterator findItemForTreeItem(const QTreeWidgetItem* item) const + { + for (std::list::const_iterator it = items.begin(); it!=items.end(); ++it) { + if (it->item == item) { + return it; + } + } + return items.end(); + } + }; -ManageUserParamsDialog::ManageUserParamsDialog(DockablePanel* panel,QWidget* parent) +ManageUserParamsDialog::ManageUserParamsDialog(DockablePanel* panel, QWidget* parent) : QDialog(parent) , _imp(new ManageUserParamsDialogPrivate(panel)) { + Natron::EffectInstance* effect = dynamic_cast(panel->getHolder()); + QString title = "User Parameters"; + if (effect) { + title += " for "; + title += effect->getScriptName().c_str(); + } + setWindowTitle(title); _imp->mainLayout = new QHBoxLayout(this); - _imp->tree = new QTreeWidget(this); + _imp->tree = new UserParamsDialogTreeWidget(this); _imp->tree->setSelectionMode(QAbstractItemView::SingleSelection); _imp->tree->setSelectionBehavior(QAbstractItemView::SelectRows); //_imp->tree->setRootIsDecorated(false); @@ -123,11 +163,13 @@ ManageUserParamsDialog::ManageUserParamsDialog(DockablePanel* panel,QWidget* par _imp->tree->header()->setStretchLastSection(true); _imp->tree->header()->hide(); - TreeItem userPageItem; + /*TreeItem userPageItem; userPageItem.item = new QTreeWidgetItem(_imp->tree); userPageItem.item->setText(0, NATRON_USER_MANAGED_KNOBS_PAGE); userPageItem.item->setExpanded(true); - _imp->items.push_back(userPageItem); + userPageItem.scriptName = NATRON_USER_MANAGED_KNOBS_PAGE; + + _imp->items.push_back(userPageItem);*/ QObject::connect(_imp->tree, SIGNAL(itemSelectionChanged()),this,SLOT(onSelectionChanged())); QObject::connect(_imp->tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(onItemDoubleClicked(QTreeWidgetItem*,int))); @@ -135,30 +177,39 @@ ManageUserParamsDialog::ManageUserParamsDialog(DockablePanel* panel,QWidget* par std::list markedKnobs; const std::vector >& knobs = panel->getHolder()->getKnobs(); for (std::vector >::const_iterator it = knobs.begin(); it != knobs.end(); ++it) { - if ((*it)->isUserKnob()) { - - if ((*it)->getParentKnob()) { - qDebug() << (*it)->getParentKnob()->getName().c_str(); - } - KnobPage* page = dynamic_cast(it->get()); - if (page) { + + + KnobPage* page = dynamic_cast(it->get()); + if (page) { + + TreeItem pageItem; + /* if (page->getName() == NATRON_USER_MANAGED_KNOBS_PAGE) { + TreeItem & item = _imp->items.front(); + item.knob = *it; - TreeItem pageItem; - if (page->getName() == NATRON_USER_MANAGED_KNOBS_PAGE) { - pageItem.item = userPageItem.item; - } else { - pageItem.item = new QTreeWidgetItem(_imp->tree); - pageItem.item->setText(0, page->getName().c_str()); - pageItem.knob = *it; - pageItem.item->setExpanded(true); - } + //Reposition the tree item correctly + delete item.item; + item.item = new QTreeWidgetItem(_imp->tree); + item.item->setText(0, NATRON_USER_MANAGED_KNOBS_PAGE); + item.item->setExpanded(true); + pageItem = userPageItem; + } else {*/ + pageItem.item = new QTreeWidgetItem(_imp->tree); + pageItem.scriptName = page->getName().c_str(); + pageItem.item->setText(0, pageItem.scriptName); + pageItem.knob = *it; + pageItem.item->setExpanded(true); _imp->items.push_back(pageItem); + //} + + if ((*it)->isUserKnob()) { std::vector > children = page->getChildren(); _imp->initializeKnobs(children, pageItem.item, markedKnobs); - } + } + } _imp->mainLayout->addWidget(_imp->tree); @@ -214,6 +265,27 @@ ManageUserParamsDialog::~ManageUserParamsDialog() // } } +static QString createTextForKnob(const boost::shared_ptr& knob) +{ + QString text = knob->getName().c_str(); + std::list > listeners; + knob->getListeners(listeners); + if (!listeners.empty()) { + boost::shared_ptr listener = listeners.front(); + if (listener->getAliasMaster() == knob) { + text += " (alias of "; + Natron::EffectInstance* effect = dynamic_cast(listener->getHolder()); + if (effect) { + text += effect->getScriptName_mt_safe().c_str(); + text += '.'; + } + text += listener->getName().c_str(); + text += ')'; + } + } + return text; +} + void ManageUserParamsDialogPrivate::initializeKnobs(const std::vector >& knobs,QTreeWidgetItem* parent,std::list& markedKnobs) { @@ -228,7 +300,8 @@ ManageUserParamsDialogPrivate::initializeKnobs(const std::vectorsetText(0, (*it2)->getName().c_str()); + i.scriptName = (*it2)->getName().c_str(); + i.item->setText(0, createTextForKnob(i.knob)); i.item->setExpanded(true); items.push_back(i); @@ -241,12 +314,6 @@ ManageUserParamsDialogPrivate::initializeKnobs(const std::vector -ManageUserParamsDialogPrivate::getUserPageKnob() const -{ - return panel->getUserPageKnob(); -} - void ManageUserParamsDialogPrivate::rebuildUserPages() @@ -260,10 +327,13 @@ ManageUserParamsDialog::onPickClicked() PickKnobDialog dialog(_imp->panel,this); if (dialog.exec()) { bool useAlias; - KnobGui* selectedKnob = dialog.getSelectedKnob(&useAlias); + boost::shared_ptr page; + boost::shared_ptr group; + KnobGui* selectedKnob = dialog.getSelectedKnob(&useAlias,&page,&group); if (!selectedKnob) { return; } + boost::shared_ptr hadUserPage = _imp->panel->getUserPageKnob(); NodeSettingsPanel* nodePanel = dynamic_cast(_imp->panel); assert(nodePanel); @@ -271,30 +341,69 @@ ManageUserParamsDialog::onPickClicked() assert(nodeGui); NodePtr node = nodeGui->getNode(); assert(node); - boost::shared_ptr duplicate = selectedKnob->createDuplicateOnNode(node->getLiveInstance(), useAlias); - _imp->onKnobAddedInternal(duplicate); + boost::shared_ptr duplicate = selectedKnob->createDuplicateOnNode(node->getLiveInstance(), useAlias, page, group, -1); + if (duplicate) { + + bool hasCreatedUserPage = false; + if (!hadUserPage) { + hasCreatedUserPage = _imp->createUserPageItem(); + } + _imp->createItemForKnob(duplicate); + + _imp->saveAndRebuildPages(); + + if (hasCreatedUserPage) { + _imp->panel->setUserPageActiveIndex(); + } + } } } void ManageUserParamsDialog::onAddClicked() { + boost::shared_ptr hadUserPage = _imp->panel->getUserPageKnob(); AddKnobDialog dialog(_imp->panel,boost::shared_ptr(),this); if (dialog.exec()) { //Ensure the user page knob exists - boost::shared_ptr userPageKnob = _imp->panel->getUserPageKnob(); - (void)userPageKnob; + bool hasCreatedUserPage = false; + if (!hadUserPage) { + hasCreatedUserPage = _imp->createUserPageItem(); + } boost::shared_ptr knob = dialog.getKnob(); - _imp->onKnobAddedInternal(knob); + _imp->createItemForKnob(knob); + _imp->saveAndRebuildPages(); + if (hasCreatedUserPage) { + _imp->panel->setUserPageActiveIndex(); + } } } -void -ManageUserParamsDialogPrivate::onKnobAddedInternal(const boost::shared_ptr& knob) +bool +ManageUserParamsDialogPrivate::createUserPageItem() +{ + boost::shared_ptr userPageKnob = panel->getUserPageKnob(); + if (!userPageKnob) { + return false; + } + for (std::list::iterator it = items.begin(); it!=items.end(); ++it) { + if (it->knob == userPageKnob) { + return false; + } + } + createItemForKnob(userPageKnob, -1); + return true; +} + +QTreeWidgetItem* +ManageUserParamsDialogPrivate::createItemForKnob(const boost::shared_ptr& knob,int insertIndex) { QTreeWidgetItem* parent = 0; - boost::shared_ptr parentKnob = knob->getParentKnob(); + boost::shared_ptr parentKnob; + if (knob) { + parentKnob = knob->getParentKnob(); + } if (parentKnob) { for (std::list::iterator it = items.begin(); it != items.end(); ++it) { if (it->knob.get() == parentKnob.get()) { @@ -308,7 +417,7 @@ ManageUserParamsDialogPrivate::onKnobAddedInternal(const boost::shared_ptr::iterator it = items.begin(); it != items.end(); ++it) { - if (it->item->text(0) == QString(NATRON_USER_MANAGED_KNOBS_PAGE)) { + if (it->scriptName == QString(NATRON_USER_MANAGED_KNOBS_PAGE)) { parent = it->item; break; } @@ -320,14 +429,32 @@ ManageUserParamsDialogPrivate::onKnobAddedInternal(const boost::shared_ptraddChild(i.item); + if (insertIndex == -1 || insertIndex >= parent->childCount()) { + parent->addChild(i.item); + } else { + parent->insertChild(insertIndex, i.item); + } parent->setExpanded(true); } else { - tree->addTopLevelItem(i.item); + if (insertIndex == -1 || insertIndex >= tree->topLevelItemCount()) { + tree->addTopLevelItem(i.item); + } else { + tree->insertTopLevelItem(insertIndex, i.item); + } } - i.item->setText(0, knob->getName().c_str()); + i.item->setExpanded(true); + i.scriptName = knob->getName().c_str(); + + i.item->setText(0, createTextForKnob(i.knob)); items.push_back(i); + return i.item; + +} + +void +ManageUserParamsDialogPrivate::saveAndRebuildPages() +{ rebuildUserPages(); panel->getGui()->getApp()->triggerAutoSave(); } @@ -356,11 +483,11 @@ ManageUserParamsDialog::onDeleteClicked() delete it->item; _imp->items.erase(it); - boost::shared_ptr userPage = _imp->getUserPageKnob(); - if (userPage->getChildren().empty()) { + boost::shared_ptr userPage = _imp->panel->getUserPageKnob(); + if (userPage && userPage->getChildren().empty()) { userPage->getHolder()->removeDynamicKnob(userPage.get()); } - _imp->panel->getGui()->getApp()->triggerAutoSave(); + _imp->saveAndRebuildPages(); break; } } @@ -375,15 +502,21 @@ ManageUserParamsDialog::onEditClickedInternal(const QList &sel for (int i = 0; i < selection.size(); ++i) { for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { if (it->item == selection[i]) { - - AddKnobDialog dialog(_imp->panel,it->knob,this); + AddKnobDialog dialog(_imp->panel, it->knob, this); if (dialog.exec()) { - - - it->knob = dialog.getKnob(); - it->item->setText(0, it->knob->getName().c_str()); - _imp->rebuildUserPages(); - _imp->panel->getGui()->getApp()->triggerAutoSave(); + int indexIndParent = -1; + QTreeWidgetItem* parent = it->item->parent(); + if (parent) { + indexIndParent = parent->indexOfChild(it->item); + } + delete it->item; + _imp->items.erase(it); + boost::shared_ptr knob = dialog.getKnob(); + QTreeWidgetItem* item = _imp->createItemForKnob(knob,indexIndParent); + _imp->saveAndRebuildPages(); + QItemSelectionModel* model = _imp->tree->selectionModel(); + model->select(_imp->tree->indexFromItemPublic(item), QItemSelectionModel::ClearAndSelect); + break; } } @@ -394,146 +527,175 @@ ManageUserParamsDialog::onEditClickedInternal(const QList &sel } void -ManageUserParamsDialog::onEditClicked() +ManageUserParamsDialog::keyPressEvent(QKeyEvent* e) { + if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) { + if (_imp->removeButton->isEnabled()) { + onDeleteClicked(); + e->accept(); + return; + } + } + QDialog::keyPressEvent(e); +} + +void +ManageUserParamsDialog::onEditClicked() +{ QList selection = _imp->tree->selectedItems(); onEditClickedInternal(selection); - } void ManageUserParamsDialog::onUpClicked() { QList selection = _imp->tree->selectedItems(); - if (!selection.isEmpty()) { - for (int i = 0; i < selection.size(); ++i) { - for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { - if (it->item == selection[i]) { - - if (dynamic_cast(it->knob.get())) { - break; - } - QTreeWidgetItem* parent = 0; - boost::shared_ptr parentKnob = it->knob->getParentKnob(); - if (parentKnob) { - if (parentKnob->getName() == NATRON_USER_MANAGED_KNOBS_PAGE) { - for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { - if (it->item->text(0) == QString(NATRON_USER_MANAGED_KNOBS_PAGE)) { - parent = it->item; - break; - } - } - } else { - for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { - if (it->knob == parentKnob) { - parent = it->item; - break; - } - } + if (selection.empty()) { + return; + } + QTreeWidgetItem* selectedItem = selection.front(); + for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { + if (it->item == selectedItem) { + + QTreeWidgetItem* parent = 0; + boost::shared_ptr parentKnob; + if (it->knob) { + parentKnob = it->knob->getParentKnob(); + } + if (parentKnob) { + if (parentKnob->getName() == NATRON_USER_MANAGED_KNOBS_PAGE) { + for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { + if (it->scriptName == QString(NATRON_USER_MANAGED_KNOBS_PAGE)) { + parent = it->item; + break; } } - - int index; - if (!parent) { - index = _imp->tree->indexOfTopLevelItem(it->item); - } else { - index = parent->indexOfChild(it->item); - } - if (index == 0) { - break; - } - _imp->panel->getHolder()->moveKnobOneStepUp(it->knob.get()); - QList children = it->item->takeChildren(); - delete it->item; - - it->item = new QTreeWidgetItem; - it->item->setText(0, it->knob->getName().c_str()); - if (!parent) { - _imp->tree->insertTopLevelItem(index - 1, it->item); - } else { - parent->insertChild(index - 1, it->item); + } else { + for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { + if (it->knob == parentKnob) { + parent = it->item; + break; + } } - it->item->insertChildren(0, children); - it->item->setExpanded(true); - _imp->tree->clearSelection(); - it->item->setSelected(true); - break; } } + int index; + if (!parent) { + index = _imp->tree->indexOfTopLevelItem(it->item); + } else { + index = parent->indexOfChild(it->item); + } + if (index == 0) { + break; + } + + if (!it->knob || !_imp->panel->getHolder()->moveKnobOneStepUp(it->knob.get())) { + return; + } + QList children = it->item->takeChildren(); + delete it->item; + + boost::shared_ptr knob = it->knob; + //invalidates iterator + _imp->items.erase(it); + + QTreeWidgetItem* item = _imp->createItemForKnob(knob, index -1); + item->insertChildren(0, children); + _imp->saveAndRebuildPages(); + QItemSelectionModel* model = _imp->tree->selectionModel(); + model->select(_imp->tree->indexFromItemPublic(item), QItemSelectionModel::ClearAndSelect); + + boost::shared_ptr isPage = boost::dynamic_pointer_cast(knob); + if (isPage) { + _imp->panel->setPageActiveIndex(isPage); + } + + break; } - _imp->rebuildUserPages(); } + + } void ManageUserParamsDialog::onDownClicked() { QList selection = _imp->tree->selectedItems(); - if (!selection.isEmpty()) { - for (int i = 0; i < selection.size(); ++i) { - for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { - if (it->item == selection[i]) { - if (dynamic_cast(it->knob.get())) { - break; - } - - QTreeWidgetItem* parent = 0; - boost::shared_ptr parentKnob = it->knob->getParentKnob(); - if (parentKnob) { - if (parentKnob->getName() == NATRON_USER_MANAGED_KNOBS_PAGE) { - for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { - if (it->item->text(0) == QString(NATRON_USER_MANAGED_KNOBS_PAGE)) { - parent = it->item; - break; - } - } - } else { - for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { - if (it->knob == parentKnob) { - parent = it->item; - break; - } - } - } - } - int index; - - if (!parent) { - index = _imp->tree->indexOfTopLevelItem(it->item); - if (index == _imp->tree->topLevelItemCount() - 1) { + if (selection.empty()) { + return; + } + QTreeWidgetItem* selectedItem = selection.front(); + + for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { + if (it->item == selectedItem) { + + + //Find the parent item + QTreeWidgetItem* parent = 0; + boost::shared_ptr parentKnob; + if (it->knob) { + parentKnob = it->knob->getParentKnob(); + } + if (parentKnob) { + if (parentKnob->getName() == NATRON_USER_MANAGED_KNOBS_PAGE) { + for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { + if (it->scriptName == QString(NATRON_USER_MANAGED_KNOBS_PAGE)) { + parent = it->item; break; } - } else { - index = parent->indexOfChild(it->item); - if (index == parent->childCount() - 1) { + } + } else { + for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { + if (it->knob == parentKnob) { + parent = it->item; break; } } - - _imp->panel->getHolder()->moveKnobOneStepDown(it->knob.get()); - QList children = it->item->takeChildren(); - delete it->item; - - - it->item = new QTreeWidgetItem; - if (parent) { - parent->insertChild(index + 1, it->item); - } else { - _imp->tree->insertTopLevelItem(index + 1, it->item); - } - it->item->setText(0, it->knob->getName().c_str()); - it->item->insertChildren(0, children); - it->item->setExpanded(true); - _imp->tree->clearSelection(); - it->item->setSelected(true); + } + } + int index; + + if (!parent) { + index = _imp->tree->indexOfTopLevelItem(it->item); + if (index == _imp->tree->topLevelItemCount() - 1) { + break; + } + } else { + index = parent->indexOfChild(it->item); + if (index == parent->childCount() - 1) { break; } } + bool moveOk = false; + if (it->knob) { + moveOk = _imp->panel->getHolder()->moveKnobOneStepDown(it->knob.get()); + } + if (!moveOk) { + break; + } + + QList children = it->item->takeChildren(); + delete it->item; + boost::shared_ptr knob = it->knob; + //invalidates iterator + _imp->items.erase(it); + + QTreeWidgetItem* item = _imp->createItemForKnob(knob, index + 1); + item->insertChildren(0, children); + _imp->saveAndRebuildPages(); + QItemSelectionModel* model = _imp->tree->selectionModel(); + model->select(_imp->tree->indexFromItemPublic(item), QItemSelectionModel::ClearAndSelect); + + boost::shared_ptr isPage = boost::dynamic_pointer_cast(knob); + if (isPage) { + _imp->panel->setPageActiveIndex(isPage); + } + + break; } - _imp->rebuildUserPages(); } } @@ -550,6 +712,9 @@ ManageUserParamsDialog::onItemDoubleClicked(QTreeWidgetItem *item, int /*column* if (item) { selection.push_back(item); } + if (!_imp->editButton->isEnabled()) { + return; + } onEditClickedInternal(selection); } @@ -558,22 +723,21 @@ ManageUserParamsDialog::onSelectionChanged() { QList selection = _imp->tree->selectedItems(); bool canEdit = true; - bool canMove = true; bool canDelete = true; if (!selection.isEmpty()) { QTreeWidgetItem* item = selection[0]; if (item->text(0) == QString(NATRON_USER_MANAGED_KNOBS_PAGE)) { canEdit = false; - canDelete = false; - canMove = false; } for (std::list::iterator it = _imp->items.begin(); it != _imp->items.end(); ++it) { if (it->item == item) { KnobPage* isPage = dynamic_cast(it->knob.get()); KnobGroup* isGroup = dynamic_cast(it->knob.get()); if (isPage) { - canMove = false; canEdit = false; + if (!isPage->isUserKnob()) { + canDelete = false; + } } else if (isGroup) { canEdit = false; } @@ -584,6 +748,6 @@ ManageUserParamsDialog::onSelectionChanged() _imp->removeButton->setEnabled(selection.size() == 1 && canDelete); _imp->editButton->setEnabled(selection.size() == 1 && canEdit); - _imp->upButton->setEnabled(selection.size() == 1 && canMove); - _imp->downButton->setEnabled(selection.size() == 1 && canMove); + _imp->upButton->setEnabled(selection.size() == 1); + _imp->downButton->setEnabled(selection.size() == 1); } diff --git a/Gui/ManageUserParamsDialog.h b/Gui/ManageUserParamsDialog.h index b0939ec566..bb252e96b5 100644 --- a/Gui/ManageUserParamsDialog.h +++ b/Gui/ManageUserParamsDialog.h @@ -31,17 +31,21 @@ #include #endif +CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include +CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -class DockablePanel; -class QTreeWidgetItem; +#include "Gui/GuiFwd.h" + struct ManageUserParamsDialogPrivate; class ManageUserParamsDialog : public QDialog { + GCC_DIAG_SUGGEST_OVERRIDE_OFF Q_OBJECT + GCC_DIAG_SUGGEST_OVERRIDE_ON public: @@ -72,6 +76,8 @@ public Q_SLOTS: private: + virtual void keyPressEvent(QKeyEvent* e) OVERRIDE FINAL; + void onEditClickedInternal(const QList &selection); boost::scoped_ptr _imp; diff --git a/Gui/Menu.h b/Gui/Menu.h index ed7a8ab5ea..4ba774d7fa 100644 --- a/Gui/Menu.h +++ b/Gui/Menu.h @@ -26,12 +26,16 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) +#include "Gui/GuiFwd.h" + + namespace Natron { class Menu : public QMenu diff --git a/Gui/MessageBox.h b/Gui/MessageBox.h index 4c8300a68e..30f43c805e 100644 --- a/Gui/MessageBox.h +++ b/Gui/MessageBox.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef _NATRON_MESSAGE_BOX_H #define _NATRON_MESSAGE_BOX_H @@ -26,11 +25,12 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif -#include "Global/Macros.h" CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -39,8 +39,8 @@ CLANG_DIAG_ON(uninitialized) #include "Global/GlobalDefines.h" -class QCheckBox; -class QAbstractButton; +#include "Gui/GuiFwd.h" + namespace Natron { struct MessageBoxPrivate; diff --git a/Gui/MultiInstancePanel.cpp b/Gui/MultiInstancePanel.cpp index 456da9d0d2..0484f8b76f 100644 --- a/Gui/MultiInstancePanel.cpp +++ b/Gui/MultiInstancePanel.cpp @@ -1905,7 +1905,11 @@ TrackerPanel::onAverageTracksButtonClicked() } } QString newName = QString("Average%1").arg(avgIndex + 1); - newInstance->setScriptName(newName.toStdString()); + try { + newInstance->setScriptName(newName.toStdString()); + } catch (...) { + + } newInstance->updateEffectLabelKnob(newName); boost::shared_ptr newInstanceCenter = getCenterKnobForTracker( newInstance.get() ); diff --git a/Gui/MultiInstancePanel.h b/Gui/MultiInstancePanel.h index b8634a01a4..f7501e9852 100644 --- a/Gui/MultiInstancePanel.h +++ b/Gui/MultiInstancePanel.h @@ -25,22 +25,25 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif + +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) +#include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + #include "Engine/Knob.h" -#include -namespace Natron { -class Node; -} -class NodeGui; -class QVBoxLayout; -class QHBoxLayout; -class QItemSelection; -class TableItem; -class KnobButton; -class Gui; +#include "Engine/EngineFwd.h" + +#include "Gui/GuiFwd.h" + + /** * @brief This class represents a multi-instance settings panel. **/ diff --git a/Gui/NewLayerDialog.h b/Gui/NewLayerDialog.h index a14d5d6b4d..6367241b7d 100644 --- a/Gui/NewLayerDialog.h +++ b/Gui/NewLayerDialog.h @@ -25,19 +25,20 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif -#include "Global/Macros.h" - +CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include +CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -namespace Natron { - class ImageComponents; -} +#include "Gui/GuiFwd.h" + struct NewLayerDialogPrivate; class NewLayerDialog : public QDialog diff --git a/Gui/NodeBackDropSerialization.h b/Gui/NodeBackDropSerialization.h index 8b72dcfb6d..53a1e57671 100644 --- a/Gui/NodeBackDropSerialization.h +++ b/Gui/NodeBackDropSerialization.h @@ -26,9 +26,10 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include -#include "Global/Macros.h" #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_OFF GCC_DIAG_OFF(unused-parameter) @@ -43,6 +44,9 @@ GCC_DIAG_ON(unused-parameter) #include "Engine/KnobSerialization.h" +#include "Gui/GuiFwd.h" + + #define NODE_BACKDROP_INTRODUCES_SELECTED 2 #define NODE_BACKDROP_SERIALIZATION_VERSION NODE_BACKDROP_INTRODUCES_SELECTED diff --git a/Gui/NodeClipBoard.h b/Gui/NodeClipBoard.h index 30b43674d2..eee4d61ae3 100644 --- a/Gui/NodeClipBoard.h +++ b/Gui/NodeClipBoard.h @@ -19,25 +19,26 @@ #ifndef Gui_NodeClipBoard_h #define Gui_NodeClipBoard_h - // ***** BEGIN PYTHON BLOCK ***** // from : // "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif -class NodeSerialization; -class NodeGuiSerialization; +#include "Gui/GuiFwd.h" -struct NodeClipBoard +class NodeClipBoard { +public: std::list > nodes; std::list > nodesUI; diff --git a/Gui/NodeCreationDialog.h b/Gui/NodeCreationDialog.h index 6456ad6037..562a4a875f 100644 --- a/Gui/NodeCreationDialog.h +++ b/Gui/NodeCreationDialog.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef NODECREATIONDIALOG_H #define NODECREATIONDIALOG_H @@ -26,13 +25,13 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -40,11 +39,11 @@ CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Gui/LineEdit.h" +#include "Gui/GuiFwd.h" + -class QStringList; -class QModelIndex; -class QListView; struct CompleterLineEditPrivate; + class CompleterLineEdit : public LineEdit { diff --git a/Gui/NodeGraph.cpp b/Gui/NodeGraph.cpp index 16592700b6..e79ccf49bb 100644 --- a/Gui/NodeGraph.cpp +++ b/Gui/NodeGraph.cpp @@ -41,6 +41,7 @@ #include "Engine/TimeLine.h" #include "Gui/BackDropGui.h" +#include "Gui/DotGui.h" #include "Gui/Edge.h" #include "Gui/Gui.h" #include "Gui/GuiAppInstance.h" diff --git a/Gui/NodeGraph.h b/Gui/NodeGraph.h index 3d8b9f2729..e2caa6da12 100644 --- a/Gui/NodeGraph.h +++ b/Gui/NodeGraph.h @@ -40,30 +40,16 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) +#include "Global/GlobalDefines.h" #include "Engine/NodeGraphI.h" -#include "Global/GlobalDefines.h" +#include "Engine/EngineFwd.h" + #include "Gui/PanelWidget.h" +#include "Gui/GuiFwd.h" + -class QVBoxLayout; -class QScrollArea; -class QEvent; -class QKeyEvent; -class Gui; -class NodeGui; -class QDropEvent; -class QUndoCommand; -class QDragEnterEvent; -class NodeSerialization; -class NodeGuiSerialization; -class NodeBackDropSerialization; -class NodeCollection; -class ViewerTab; -struct NodeClipBoard; -struct NodeGraphPrivate; -namespace Natron { -class Node; -} +class NodeGraphPrivate; class NodeGraph : public QGraphicsView, public NodeGraphI, public PanelWidget, public boost::noncopyable { diff --git a/Gui/NodeGraphPrivate.h b/Gui/NodeGraphPrivate.h index 4decd74e9d..e5192a4419 100644 --- a/Gui/NodeGraphPrivate.h +++ b/Gui/NodeGraphPrivate.h @@ -25,17 +25,16 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include #include - #include #include #include @@ -48,13 +47,8 @@ CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Gui/NodeGraphUndoRedo.h" // NodeGuiPtr +#include "Gui/GuiFwd.h" -class NodeGraph; -class Gui; -class NodeCollection; -struct NodeClipBoard; -class NodeGuiSerialization; -class ViewerTab; #define NATRON_CACHE_SIZE_TEXT_REFRESH_INTERVAL_MS 1000 @@ -156,8 +150,9 @@ class Navigator -struct NodeGraphPrivate +class NodeGraphPrivate { +public: NodeGraph* _publicInterface; boost::weak_ptr group; diff --git a/Gui/NodeGraphPrivate10.cpp b/Gui/NodeGraphPrivate10.cpp index d68a97889d..82cdbe6197 100644 --- a/Gui/NodeGraphPrivate10.cpp +++ b/Gui/NodeGraphPrivate10.cpp @@ -31,6 +31,7 @@ #include "Engine/Project.h" #include "Engine/RotoLayer.h" +#include "Gui/DotGui.h" #include "Gui/Edge.h" #include "Gui/Gui.h" #include "Gui/GuiAppInstance.h" @@ -43,9 +44,9 @@ using namespace Natron; - void -NodeGraphPrivate::pasteNodesInternal(const NodeClipBoard & clipboard,const QPointF& scenePos, +NodeGraphPrivate::pasteNodesInternal(const NodeClipBoard & clipboard, + const QPointF& scenePos, bool useUndoCommand, std::list > > *newNodes) { @@ -155,9 +156,6 @@ NodeGraphPrivate::pasteNode(const NodeSerialization & internalSerialization, } else { //If we paste the node in a different graph, it can keep its scriptname/label - /*name = internalSerialization.getNodeScriptName(); - n->setScriptName( name); - n->setLabel(internalSerialization.getNodeLabel());*/ } @@ -172,7 +170,8 @@ NodeGraphPrivate::pasteNode(const NodeSerialization & internalSerialization, } } std::list > allNodes; - _publicInterface->getGui()->getApp()->getProject()->getActiveNodes(&allNodes); + + _publicInterface->getGui()->getApp()->getProject()->getNodes_recursive(allNodes, true); n->restoreKnobsLinks(internalSerialization,allNodes); //We don't want the clone to have the same hash as the original diff --git a/Gui/NodeGraphTextItem.h b/Gui/NodeGraphTextItem.h index 231329b78c..ac1613ea0c 100644 --- a/Gui/NodeGraphTextItem.h +++ b/Gui/NodeGraphTextItem.h @@ -25,10 +25,16 @@ #include // ***** END PYTHON BLOCK ***** -#include #include "Global/Macros.h" -class NodeGraph; +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) +#include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + +#include "Gui/GuiFwd.h" + class NodeGraphTextItem : public QGraphicsTextItem { NodeGraph* _graph; diff --git a/Gui/NodeGraphUndoRedo.cpp b/Gui/NodeGraphUndoRedo.cpp index c8acc0d8a3..1b572df62d 100644 --- a/Gui/NodeGraphUndoRedo.cpp +++ b/Gui/NodeGraphUndoRedo.cpp @@ -1207,6 +1207,14 @@ LoadNodePresetsCommand::redo() panel->addInstances(newChildren); } } + + NodeList allNodes; + internalNode->getGroup()->getActiveNodes(&allNodes); + NodeGroup* isGroup = dynamic_cast(internalNode->getLiveInstance()); + if (isGroup) { + isGroup->getActiveNodes(&allNodes); + } + internalNode->restoreKnobsLinks(*_newSerializations.front(), allNodes); internalNode->getLiveInstance()->evaluate_public(NULL, true, Natron::eValueChangedReasonUserEdited); internalNode->getApp()->triggerAutoSave(); _firstRedoCalled = true; @@ -1622,7 +1630,11 @@ GroupFromSelectionCommand::GroupFromSelectionCommand(NodeGraph* graph,const Node CreateNodeArgs::DefaultValuesList(), isGrp); NodePtr output = graph->getGui()->getApp()->createNode(args); - output->setScriptName("Output"); + try { + output->setScriptName("Output"); + } catch (...) { + + } assert(output); double thisNodeX,thisNodeY; diff --git a/Gui/NodeGraphUndoRedo.h b/Gui/NodeGraphUndoRedo.h index 8037d61318..577b79b3b7 100644 --- a/Gui/NodeGraphUndoRedo.h +++ b/Gui/NodeGraphUndoRedo.h @@ -25,7 +25,8 @@ #include // ***** END PYTHON BLOCK ***** -#include "Global/GlobalDefines.h" +#include "Global/Macros.h" + #include #include #include @@ -35,22 +36,22 @@ #endif #include +#include "Global/GlobalDefines.h" + +#include "Engine/EngineFwd.h" + +#include "Gui/GuiFwd.h" + + /** * This file gathers undo/redo command associated to the node graph. Each of them triggers an autosave when redone/undone * except the move command. **/ -class Edge; -class NodeGui; -class NodeGraph; -class NodeSerialization; typedef boost::shared_ptr NodeGuiPtr; typedef std::list NodeGuiList; -namespace Natron { -class Node; -} class MoveMultipleNodesCommand diff --git a/Gui/NodeGui.cpp b/Gui/NodeGui.cpp index 6fd4adf693..0aa1cc7970 100644 --- a/Gui/NodeGui.cpp +++ b/Gui/NodeGui.cpp @@ -848,7 +848,7 @@ NodeGui::resize(int width, _expressionIndicator->refreshPosition( topLeft + QPointF(width,0) ); _availableViewsIndicator->refreshPosition(topLeft); - _passThroughIndicator->refreshPosition(bottomRight - QPointF(NATRON_ELLIPSE_WARN_DIAMETER / 2,NATRON_ELLIPSE_WARN_DIAMETER / 2)); + _passThroughIndicator->refreshPosition(bottomRight ); _persistentMessage->setPos(topLeft.x() + (width / 2) - (pMWidth / 2), topLeft.y() + height / 2 - metrics.height() / 2); _stateIndicator->setRect(topLeft.x() - NATRON_STATE_INDICATOR_OFFSET,topLeft.y() - NATRON_STATE_INDICATOR_OFFSET, @@ -1439,7 +1439,9 @@ NodeGui::refreshEdgesVisibilityInternal(bool hovered) continue; } if (!inputAsideDisplayed) { - inputAsideDisplayed = true; + if (!_inputEdges[i]->getSource()) { + inputAsideDisplayed = true; + } } else { _inputEdges[i]->setVisible(false); } @@ -1546,7 +1548,8 @@ NodeGui::setUserSelected(bool b) bool NodeGui::getIsSelected() const { - QMutexLocker l(&_selectedMutex); return _selected; + QMutexLocker l(&_selectedMutex); + return _selected; } @@ -2922,93 +2925,6 @@ NodeGui::onParentMultiInstancePositionChanged(int x, refreshPosition(x, y,true); } -//////////Dot node gui -DotGui::DotGui(QGraphicsItem* parent) -: NodeGui(parent) -, diskShape(NULL) -, ellipseIndicator(NULL) -{ -} - -void -DotGui::createGui() -{ - double depth = getBaseDepth(); - setZValue(depth); - - diskShape = new QGraphicsEllipseItem(this); - diskShape->setZValue(depth); - QPointF topLeft = mapFromParent( pos() ); - diskShape->setRect( QRectF(topLeft.x(),topLeft.y(),DOT_GUI_DIAMETER,DOT_GUI_DIAMETER) ); - - ellipseIndicator = new QGraphicsEllipseItem(this); - ellipseIndicator->setRect(QRectF(topLeft.x() - NATRON_STATE_INDICATOR_OFFSET, - topLeft.y() - NATRON_STATE_INDICATOR_OFFSET, - DOT_GUI_DIAMETER + NATRON_STATE_INDICATOR_OFFSET * 2, - DOT_GUI_DIAMETER + NATRON_STATE_INDICATOR_OFFSET * 2)); - ellipseIndicator->hide(); -} - -void -DotGui::refreshStateIndicator() -{ - bool showIndicator = true; - if (getIsSelected()) { - ellipseIndicator->setBrush(QColor(255,255,255,128)); - } else { - showIndicator = false; - } - - if (showIndicator && !ellipseIndicator->isVisible()) { - ellipseIndicator->show(); - } else if (!showIndicator && ellipseIndicator->isVisible()) { - ellipseIndicator->hide(); - } else { - update(); - } - -} - -void -DotGui::applyBrush(const QBrush & brush) -{ - diskShape->setBrush(brush); -} - -NodeSettingsPanel* -DotGui::createPanel(QVBoxLayout* container, - const boost::shared_ptr & thisAsShared) -{ - NodeSettingsPanel* panel = new NodeSettingsPanel( boost::shared_ptr(), - getDagGui()->getGui(), - thisAsShared, - container,container->parentWidget() ); - - ///Always close the panel by default for Dots - panel->setClosed(true); - - return panel; -} - -QRectF -DotGui::boundingRect() const -{ - QTransform t; - QRectF bbox = diskShape->boundingRect(); - QPointF center = bbox.center(); - - t.translate( center.x(), center.y() ); - t.scale( scale(), scale() ); - t.translate( -center.x(), -center.y() ); - - return t.mapRect(bbox); -} - -QPainterPath -DotGui::shape() const -{ - return diskShape->shape(); -} void NodeGui::onInternalNameChanged(const QString & s) @@ -3028,10 +2944,45 @@ NodeGui::onInternalNameChanged(const QString & s) void NodeGui::setName(const QString & newName) { + + + std::string stdName = newName.toStdString(); + stdName = Natron::makeNameScriptFriendly(stdName); + std::string oldScriptName = getNode()->getScriptName(); + try { + getNode()->setScriptName(stdName); + } catch (const std::exception& e) { + Natron::errorDialog(tr("Rename").toStdString(), tr("Could not set node script-name to ").toStdString() + stdName + ": " + e.what()); + return; + } + + ///Update expressions on all knobs + const std::vector >& knobs = getNode()->getKnobs(); + for (std::vector >::const_iterator it = knobs.begin(); it != knobs.end(); ++it) { + std::list > listeners; + (*it)->getListeners(listeners); + for (std::list > ::iterator it2 = listeners.begin() ; it2 != listeners.end(); ++it2) { + for (int i = 0; i < (*it2)->getDimension() ;++i) { + + std::string expr = (*it2)->getExpression(i); + bool hasRet = (*it2)->isExpressionUsingRetVariable(i); + if (!expr.empty()) { + QString qexpr(expr.c_str()); + qexpr.replace(oldScriptName.c_str(), stdName.c_str()); + try { + (*it2)->setExpression(i, qexpr.toStdString(), hasRet); + } catch (...) { + + } + } + } + } + } + _settingNameFromGui = true; - getNode()->setLabel(newName.toStdString()); + getNode()->setLabel(stdName); _settingNameFromGui = false; - + onInternalNameChanged(newName); } @@ -3115,260 +3066,6 @@ NodeGui::getSize(double* w, double* h) const *h = s.height(); } -struct ExportGroupTemplateDialogPrivate -{ - Gui* gui; - NodeCollection* group; - QGridLayout* mainLayout; - - Natron::Label* labelLabel; - LineEdit* labelEdit; - - Natron::Label* idLabel; - LineEdit* idEdit; - - Natron::Label* groupingLabel; - LineEdit* groupingEdit; - - Natron::Label* fileLabel; - LineEdit* fileEdit; - Button* openButton; - - Natron::Label* iconPathLabel; - LineEdit* iconPath; - - Natron::Label* descriptionLabel; - LineEdit* descriptionEdit; - - QDialogButtonBox *buttons; - - ExportGroupTemplateDialogPrivate(NodeCollection* group,Gui* gui) - : gui(gui) - , group(group) - , mainLayout(0) - , labelLabel(0) - , labelEdit(0) - , idLabel(0) - , idEdit(0) - , groupingLabel(0) - , groupingEdit(0) - , fileLabel(0) - , fileEdit(0) - , openButton(0) - , iconPathLabel(0) - , iconPath(0) - , descriptionLabel(0) - , descriptionEdit(0) - , buttons(0) - { - - } -}; - -ExportGroupTemplateDialog::ExportGroupTemplateDialog(NodeCollection* group,Gui* gui,QWidget* parent) -: QDialog(parent) -, _imp(new ExportGroupTemplateDialogPrivate(group,gui)) -{ - _imp->mainLayout = new QGridLayout(this); - - - _imp->idLabel = new Natron::Label(tr("Unique ID"),this); - QString idTt = Natron::convertFromPlainText(tr("The unique ID is used by " NATRON_APPLICATION_NAME "to identify the plug-in in various " - "places in the application. Generally this contains domain and sub-domains names " - "such as fr.inria.group.XXX. If 2 plug-ins happen to have the same ID they will be " - "gathered by version. If 2 plug-ins have the same ID and version, the first loaded in the" - " search-paths will take precedence over the other."), Qt::WhiteSpaceNormal); - _imp->idEdit = new LineEdit(this); - _imp->idEdit->setPlaceholderText("org.organization.pyplugs.XXX"); - _imp->idEdit->setToolTip(idTt); - - - _imp->labelLabel = new Natron::Label(tr("Label"),this); - QString labelTt = Natron::convertFromPlainText(tr("Set the label of the group as the user will see it in the user interface."), Qt::WhiteSpaceNormal); - _imp->labelLabel->setToolTip(labelTt); - _imp->labelEdit = new LineEdit(this); - _imp->labelEdit->setPlaceholderText("MyPlugin"); - QObject::connect(_imp->labelEdit,SIGNAL(editingFinished()), this , SLOT(onLabelEditingFinished())); - _imp->labelEdit->setToolTip(labelTt); - - - _imp->groupingLabel = new Natron::Label(tr("Grouping"),this); - QString groupingTt = Natron::convertFromPlainText(tr("The grouping of the plug-in specifies where the plug-in will be located in the menus. " - "E.g: Color/Transform, or Draw. Each sub-level must be separated by a '/'."), Qt::WhiteSpaceNormal); - _imp->groupingLabel->setToolTip(groupingTt); - - _imp->groupingEdit = new LineEdit(this); - _imp->groupingEdit->setPlaceholderText("Color/Transform"); - _imp->groupingEdit->setToolTip(groupingTt); - - - _imp->iconPathLabel = new Natron::Label(tr("Icon relative path"),this); - QString iconTt = Natron::convertFromPlainText(tr("Set here the file path of an optional icon to identify the plug-in. " - "The path is relative to the Python script."), Qt::WhiteSpaceNormal); - _imp->iconPathLabel->setToolTip(iconTt); - _imp->iconPath = new LineEdit(this); - _imp->iconPath->setPlaceholderText("Label.png"); - _imp->iconPath->setToolTip(iconTt); - - _imp->descriptionLabel = new Natron::Label(tr("Description"),this); - QString descTt = Natron::convertFromPlainText(tr("Set here the (optional) plug-in description that the user will see when clicking the " - " \"?\" button on the settings panel of the node."), Qt::WhiteSpaceNormal); - _imp->descriptionEdit = new LineEdit(this); - _imp->descriptionEdit->setToolTip(descTt); - _imp->descriptionEdit->setPlaceholderText(tr("This plug-in can be used to produce XXX effect...")); - - _imp->fileLabel = new Natron::Label(tr("Directory"),this); - QString fileTt = Natron::convertFromPlainText(tr("Specify here the directory where to export the Python script."), Qt::WhiteSpaceNormal); - _imp->fileLabel->setToolTip(fileTt); - _imp->fileEdit = new LineEdit(this); - - - _imp->fileEdit->setToolTip(fileTt); - - - QPixmap openPix; - appPTR->getIcon(Natron::NATRON_PIXMAP_OPEN_FILE, NATRON_MEDIUM_BUTTON_ICON_SIZE, &openPix); - _imp->openButton = new Button(QIcon(openPix),"",this); - _imp->openButton->setFocusPolicy(Qt::NoFocus); - _imp->openButton->setFixedSize(NATRON_MEDIUM_BUTTON_SIZE, NATRON_MEDIUM_BUTTON_SIZE); - QObject::connect( _imp->openButton, SIGNAL( clicked() ), this, SLOT( onButtonClicked() ) ); - - _imp->buttons = new QDialogButtonBox(QDialogButtonBox::StandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel), - Qt::Horizontal,this); - QObject::connect(_imp->buttons, SIGNAL(accepted()), this, SLOT(onOkClicked())); - QObject::connect(_imp->buttons, SIGNAL(rejected()), this, SLOT(reject())); - - - _imp->mainLayout->addWidget(_imp->idLabel, 0, 0 , 1 , 1); - _imp->mainLayout->addWidget(_imp->idEdit, 0, 1, 1 , 2); - _imp->mainLayout->addWidget(_imp->labelLabel, 1, 0 , 1 , 1); - _imp->mainLayout->addWidget(_imp->labelEdit, 1, 1, 1 , 2); - _imp->mainLayout->addWidget(_imp->groupingLabel, 2, 0, 1 , 1); - _imp->mainLayout->addWidget(_imp->groupingEdit, 2, 1, 1 , 2); - _imp->mainLayout->addWidget(_imp->iconPathLabel, 3, 0 , 1 , 1); - _imp->mainLayout->addWidget(_imp->iconPath, 3, 1 , 1 , 2); - _imp->mainLayout->addWidget(_imp->descriptionLabel, 4, 0 , 1 , 1); - _imp->mainLayout->addWidget(_imp->descriptionEdit, 4, 1 , 1 , 2); - _imp->mainLayout->addWidget(_imp->fileLabel, 5, 0 , 1 , 1); - _imp->mainLayout->addWidget(_imp->fileEdit, 5, 1, 1 , 1); - _imp->mainLayout->addWidget(_imp->openButton, 5, 2, 1, 1); - _imp->mainLayout->addWidget(_imp->buttons, 6, 0, 1, 3); - - resize(400,sizeHint().height()); - - -} - -ExportGroupTemplateDialog::~ExportGroupTemplateDialog() -{ - -} - -void -ExportGroupTemplateDialog::onButtonClicked() -{ - std::vector filters; - - const QString& path = _imp->gui->getLastPluginDirectory(); - SequenceFileDialog dialog(this,filters,false,SequenceFileDialog::eFileDialogModeDir,path.toStdString(),_imp->gui,false); - if (dialog.exec()) { - std::string selection = dialog.selectedFiles(); - _imp->fileEdit->setText(selection.c_str()); - QDir d = dialog.currentDirectory(); - _imp->gui->updateLastPluginDirectory(d.absolutePath()); - } -} - -void -ExportGroupTemplateDialog::onLabelEditingFinished() -{ - if (_imp->idEdit->text().isEmpty()) { - _imp->idEdit->setText(_imp->labelEdit->text()); - } -} - -void -ExportGroupTemplateDialog::onOkClicked() -{ - QString dirPath = _imp->fileEdit->text(); - - if (!dirPath.isEmpty() && dirPath[dirPath.size() - 1] == QChar('/')) { - dirPath.remove(dirPath.size() - 1, 1); - } - QDir d(dirPath); - - if (!d.exists()) { - Natron::errorDialog(tr("Error").toStdString(), tr("You must specify a directory to save the script").toStdString()); - return; - } - QString pluginLabel = _imp->labelEdit->text(); - if (pluginLabel.isEmpty()) { - Natron::errorDialog(tr("Error").toStdString(), tr("You must specify a label to name the script").toStdString()); - return; - } else { - pluginLabel = Natron::makeNameScriptFriendly(pluginLabel.toStdString()).c_str(); - } - - QString pluginID = _imp->idEdit->text(); - if (pluginID.isEmpty()) { - Natron::errorDialog(tr("Error").toStdString(), tr("You must specify a unique ID to identify the script").toStdString()); - return; - } - - QString iconPath = _imp->iconPath->text(); - QString grouping = _imp->groupingEdit->text(); - QString description = _imp->descriptionEdit->text(); - - QString filePath = d.absolutePath() + "/" + pluginLabel + ".py"; - - QStringList filters; - filters.push_back(QString(pluginLabel + ".py")); - if (!d.entryList(filters,QDir::Files | QDir::NoDotAndDotDot).isEmpty()) { - Natron::StandardButtonEnum rep = Natron::questionDialog(tr("Existing plug-in").toStdString(), - tr("A group plug-in with the same name already exists " - "would you like to " - "override it?").toStdString(), false); - if (rep == Natron::eStandardButtonNo) { - return; - } - } - - bool foundInPath = false; - QStringList groupSearchPath = appPTR->getAllNonOFXPluginsPaths(); - for (QStringList::iterator it = groupSearchPath.begin(); it != groupSearchPath.end(); ++it) { - if (!it->isEmpty() && it->at(it->size() - 1) == QChar('/')) { - it->remove(it->size() - 1, 1); - } - if (*it == dirPath) { - foundInPath = true; - } - } - - if (!foundInPath) { - - QString message = dirPath + tr(" does not exist in the group plug-in search path, would you like to add it?"); - Natron::StandardButtonEnum rep = Natron::questionDialog(tr("Plug-in path").toStdString(), - message.toStdString(), false); - - if (rep == Natron::eStandardButtonYes) { - appPTR->getCurrentSettings()->appendPythonGroupsPath(dirPath.toStdString()); - } - - } - - QFile file(filePath); - if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) { - Natron::errorDialog(tr("Error").toStdString(), QString(tr("Cannot open ") + filePath).toStdString()); - return; - } - - QTextStream ts(&file); - QString content; - _imp->group->exportGroupToPython(pluginID, pluginLabel, description, iconPath, grouping, content); - ts << content; - - accept(); -} void NodeGui::exportGroupAsPythonScript() diff --git a/Gui/NodeGui.h b/Gui/NodeGui.h index 45b96415c4..fd10e4f7f8 100644 --- a/Gui/NodeGui.h +++ b/Gui/NodeGui.h @@ -16,8 +16,8 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ -#ifndef NATRON_GUI_NODEGUI_H -#define NATRON_GUI_NODEGUI_H +#ifndef Natron_Gui_NodeGui_h +#define Natron_Gui_NodeGui_h // ***** BEGIN PYTHON BLOCK ***** // from : @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include @@ -33,8 +35,6 @@ #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -46,39 +46,15 @@ CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Global/GlobalDefines.h" + #include "Engine/NodeGuiI.h" +#include "Engine/EngineFwd.h" + +#include "Gui/GuiFwd.h" -class HostOverlay; -class Edge; -class QPainterPath; -class QScrollArea; -class NodeSettingsPanel; -class QVBoxLayout; -class QLinearGradient; -class AppInstance; -class NodeGraph; -class QAction; -class KnobI; -class NodeGuiSerialization; -class NodeSerialization; -class KnobGui; -class Gui; -class QUndoStack; -class LinkArrow; -class MultiInstancePanel; -class QMenu; -class NodeGroup; -class QUndoStack; -class QGraphicsSimpleTextItem; -class NodeGraphPixmapItem; -class NodeGraphTextItem; -class NodeCollection; -namespace Natron { -class ChannelSet; -class Node; -} struct NodeGuiIndicatorPrivate; + class NodeGuiIndicator { public: @@ -140,7 +116,10 @@ public Q_SLOTS: }; class NodeGui -: public QObject,public QGraphicsItem, public NodeGuiI, public boost::enable_shared_from_this +: public QObject +, public QGraphicsItem +, public NodeGuiI +, public boost::enable_shared_from_this { GCC_DIAG_SUGGEST_OVERRIDE_OFF Q_OBJECT @@ -680,57 +659,4 @@ public Q_SLOTS: }; -class DotGui - : public NodeGui -{ -public: - - DotGui(QGraphicsItem *parent = 0); - -private: - - - virtual void createGui() OVERRIDE FINAL; - virtual NodeSettingsPanel* createPanel(QVBoxLayout* container, const boost::shared_ptr & thisAsShared) OVERRIDE FINAL WARN_UNUSED_RETURN; - virtual bool canMakePreview() OVERRIDE FINAL WARN_UNUSED_RETURN - { - return false; - } - - virtual void refreshStateIndicator() OVERRIDE FINAL; - - virtual void applyBrush(const QBrush & brush) OVERRIDE FINAL; - - virtual bool canResize() OVERRIDE FINAL WARN_UNUSED_RETURN { return false; } - - virtual QRectF boundingRect() const OVERRIDE FINAL; - virtual QPainterPath shape() const OVERRIDE FINAL; - QGraphicsEllipseItem* diskShape; - QGraphicsEllipseItem* ellipseIndicator; -}; - -struct ExportGroupTemplateDialogPrivate; -class ExportGroupTemplateDialog : public QDialog -{ - Q_OBJECT - -public: - - ExportGroupTemplateDialog(NodeCollection* group,Gui* gui,QWidget* parent); - - virtual ~ExportGroupTemplateDialog(); - -public Q_SLOTS: - - void onButtonClicked(); - - void onOkClicked(); - - void onLabelEditingFinished(); - -private: - - boost::scoped_ptr _imp; -}; - -#endif // NATRON_GUI_NODEGUI_H +#endif // Natron_Gui_NodeGui_h diff --git a/Gui/NodeGuiSerialization.h b/Gui/NodeGuiSerialization.h index c97b651023..15f034196a 100644 --- a/Gui/NodeGuiSerialization.h +++ b/Gui/NodeGuiSerialization.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef NODEGUISERIALIZATION_H #define NODEGUISERIALIZATION_H @@ -27,6 +26,7 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_OFF GCC_DIAG_OFF(unused-parameter) @@ -38,14 +38,19 @@ GCC_DIAG_OFF(unused-parameter) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_ON GCC_DIAG_ON(unused-parameter) #endif + +#include "Engine/AppManager.h" + +#include "Gui/GuiFwd.h" + + #define NODE_GUI_INTRODUCES_COLOR 2 #define NODE_GUI_INTRODUCES_SELECTED 3 #define NODE_GUI_MERGE_BACKDROP 4 #define NODE_GUI_INTRODUCES_OVERLAY_COLOR 5 #define NODE_GUI_SERIALIZATION_VERSION NODE_GUI_INTRODUCES_OVERLAY_COLOR -#include "Engine/AppManager.h" -class NodeGui; + class NodeGuiSerialization { public: diff --git a/Gui/NodeSettingsPanel.h b/Gui/NodeSettingsPanel.h index 85952a8a17..de9a3bf417 100644 --- a/Gui/NodeSettingsPanel.h +++ b/Gui/NodeSettingsPanel.h @@ -25,10 +25,10 @@ #include // ***** END PYTHON BLOCK ***** -#include - #include "Global/Macros.h" +#include + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include @@ -48,22 +48,7 @@ CLANG_DIAG_ON(uninitialized) #include "Engine/DockablePanelI.h" #include "Gui/DockablePanel.h" - -class KnobI; -class KnobGui; -class KnobHolder; -class NodeGui; -class Gui; -class KnobPage; -class QVBoxLayout; -class Button; -class QUndoStack; -class QUndoCommand; -class QGridLayout; -class RotoPanel; -class MultiInstancePanel; -class QTabWidget; -class KnobGroup; +#include "Gui/GuiFwd.h" class NodeSettingsPanel diff --git a/Gui/PanelWidget.h b/Gui/PanelWidget.h index 523cc591b5..6c4c0a9b57 100644 --- a/Gui/PanelWidget.h +++ b/Gui/PanelWidget.h @@ -16,15 +16,15 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ +#ifndef PANELWIDGET_H +#define PANELWIDGET_H + // ***** BEGIN PYTHON BLOCK ***** // from : // "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." #include // ***** END PYTHON BLOCK ***** -#ifndef PANELWIDGET_H -#define PANELWIDGET_H - #include "Global/Macros.h" CLANG_DIAG_OFF(deprecated) @@ -35,9 +35,9 @@ CLANG_DIAG_ON(uninitialized) #include "Engine/ScriptObject.h" -class QKeyEvent; -class Gui; -class TabWidget; +#include "Gui/GuiFwd.h" + + class PanelWidget : public ScriptObject { QWidget* _thisWidget; diff --git a/Gui/PickKnobDialog.cpp b/Gui/PickKnobDialog.cpp index 3c5f8b7bfa..ac0310de94 100644 --- a/Gui/PickKnobDialog.cpp +++ b/Gui/PickKnobDialog.cpp @@ -52,34 +52,69 @@ struct PickKnobDialogPrivate { + DockablePanel* panel; QGridLayout* mainLayout; Natron::Label* selectNodeLabel; CompleterLineEdit* nodeSelectionCombo; ComboBox* knobSelectionCombo; Natron::Label* useAliasLabel; QCheckBox* useAliasCheckBox; + Natron::Label* destPageLabel; + ComboBox* destPageCombo; + Natron::Label* groupLabel; + ComboBox* groupCombo; + std::vector > pages; + std::vector > groups; QDialogButtonBox* buttons; NodeList allNodes; std::map > allKnobs; - PickKnobDialogPrivate() - : mainLayout(0) + PickKnobDialogPrivate(DockablePanel* panel) + : panel(panel) + , mainLayout(0) , selectNodeLabel(0) , nodeSelectionCombo(0) , knobSelectionCombo(0) , useAliasLabel(0) , useAliasCheckBox(0) + , destPageLabel(0) + , destPageCombo(0) + , groupLabel(0) + , groupCombo(0) + , pages() + , groups() , buttons(0) , allNodes() , allKnobs() { } + + boost::shared_ptr getSelectedGroup() const; }; +boost::shared_ptr +PickKnobDialogPrivate::getSelectedGroup() const +{ + if (!groupCombo->isVisible()) { + return boost::shared_ptr(); + } + std::string selectedItem = groupCombo->getCurrentIndexText().toStdString(); + if (selectedItem != "-") { + for (std::vector >::const_iterator it = groups.begin(); it != groups.end(); ++it) { + if ((*it)->getName() == selectedItem) { + return *it; + } + } + } + + return boost::shared_ptr(); +} + + PickKnobDialog::PickKnobDialog(DockablePanel* panel, QWidget* parent) : QDialog(parent) -, _imp(new PickKnobDialogPrivate()) +, _imp(new PickKnobDialogPrivate(panel)) { NodeSettingsPanel* nodePanel = dynamic_cast(panel); assert(nodePanel); @@ -120,17 +155,53 @@ PickKnobDialog::PickKnobDialog(DockablePanel* panel, QWidget* parent) _imp->knobSelectionCombo = new ComboBox(this); - QString useAliasTt = QObject::tr("If checked, an alias of the selected parameter will be created, coyping entirely its state. " + QString useAliasTt = Natron::convertFromPlainText(QObject::tr("If checked, an alias of the selected parameter will be created, coyping entirely its state. " "Only the script-name, label and tooltip will be editable. For choice parameters this will also " "dynamically refresh the menu entries when the original parameter's menu is changed.\n" "When unchecked a simple expression will be set linking the 2 parameters but things such as dynamic menus " - "will not be enabled."); + "will not be enabled."),Qt::WhiteSpaceNormal); _imp->useAliasLabel = new Natron::Label(tr("Make Alias:"),this); + _imp->useAliasLabel->setToolTip(useAliasTt); _imp->useAliasCheckBox = new QCheckBox(this); + _imp->useAliasCheckBox->setToolTip(useAliasTt); _imp->useAliasCheckBox->setChecked(true); QObject::connect( _imp->nodeSelectionCombo,SIGNAL( itemCompletionChosen() ),this,SLOT( onNodeComboEditingFinished() ) ); + _imp->destPageLabel = new Natron::Label(tr("Page:"),this); + QString pagett = Natron::convertFromPlainText(QObject::tr("Select the page into which the parameter will be created"), Qt::WhiteSpaceNormal); + _imp->destPageLabel->setToolTip(pagett); + _imp->destPageCombo = new ComboBox(this); + _imp->destPageCombo->setToolTip(pagett); + QObject::connect(_imp->destPageCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onPageComboIndexChanged(int))); + + const std::vector >& knobs = node->getKnobs(); + for (std::size_t i = 0; i < knobs.size(); ++i) { + if (knobs[i]->isUserKnob()) { + boost::shared_ptr isPage = boost::dynamic_pointer_cast(knobs[i]); + if (isPage) { + _imp->pages.push_back(isPage); + _imp->destPageCombo->addItem(isPage->getName().c_str()); + } else { + boost::shared_ptr isGrp = boost::dynamic_pointer_cast(knobs[i]); + if (isGrp) { + _imp->groups.push_back(isGrp); + } + } + } + } + if (_imp->destPageCombo->count() == 0) { + _imp->destPageCombo->hide(); + } + + + _imp->groupLabel = new Natron::Label(tr("Group:"), this); + QString grouptt = Natron::convertFromPlainText(QObject::tr("Select the group into which the parameter will be created"), Qt::WhiteSpaceNormal); + _imp->groupCombo = new ComboBox(this); + _imp->groupLabel->setToolTip(grouptt); + _imp->groupCombo->setToolTip(grouptt); + onPageComboIndexChanged(0); + _imp->buttons = new QDialogButtonBox(QDialogButtonBox::StandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel), Qt::Horizontal,this); QObject::connect( _imp->buttons, SIGNAL( accepted() ), this, SLOT( accept() ) ); @@ -141,7 +212,11 @@ PickKnobDialog::PickKnobDialog(DockablePanel* panel, QWidget* parent) _imp->mainLayout->addWidget(_imp->knobSelectionCombo, 0, 2, 1, 1); _imp->mainLayout->addWidget(_imp->useAliasLabel, 1, 0, 1, 1); _imp->mainLayout->addWidget(_imp->useAliasCheckBox, 1, 1, 1, 1); - _imp->mainLayout->addWidget(_imp->buttons, 2, 0, 1, 3); + _imp->mainLayout->addWidget(_imp->destPageLabel, 2, 0 , 1, 1); + _imp->mainLayout->addWidget(_imp->destPageCombo, 2, 1 , 1, 1); + _imp->mainLayout->addWidget(_imp->groupLabel, 2, 2 , 1, 1); + _imp->mainLayout->addWidget(_imp->groupCombo, 2, 3 , 1, 1); + _imp->mainLayout->addWidget(_imp->buttons, 3, 0, 1, 3); QTimer::singleShot( 25, _imp->nodeSelectionCombo, SLOT( showCompleter() ) ); @@ -176,7 +251,7 @@ PickKnobDialog::onNodeComboEditingFinished() KnobPage* isPage = dynamic_cast( knobs[j].get() ); KnobGroup* isGroup = dynamic_cast( knobs[j].get() ); if (!isButton && !isPage && !isGroup) { - QString name( knobs[j]->getLabel().c_str() ); + QString name( knobs[j]->getName().c_str() ); bool canInsertKnob = true; for (int k = 0; k < knobs[j]->getDimension(); ++k) { @@ -194,8 +269,43 @@ PickKnobDialog::onNodeComboEditingFinished() } } +void +PickKnobDialog::onPageComboIndexChanged(int index) +{ + if (_imp->pages.empty()) { + _imp->groupCombo->hide(); + } + _imp->groupCombo->clear(); + _imp->groupCombo->addItem("-"); + + std::string selectedPage = _imp->destPageCombo->itemText(index).toStdString(); + KnobPage* parentPage = 0; + + if (selectedPage == NATRON_USER_MANAGED_KNOBS_PAGE) { + parentPage = _imp->panel->getUserPageKnob().get(); + } else { + for (std::vector >::iterator it = _imp->pages.begin(); it != _imp->pages.end(); ++it) { + if ((*it)->getName() == selectedPage) { + parentPage = it->get(); + break; + } + } + } + + for (std::vector >::iterator it = _imp->groups.begin(); it != _imp->groups.end(); ++it) { + KnobPage* page = (*it)->getTopLevelPage(); + assert(page); + + ///add only grps whose parent page is the selected page + if (page == parentPage) { + _imp->groupCombo->addItem((*it)->getName().c_str()); + } + + } +} + KnobGui* -PickKnobDialog::getSelectedKnob(bool* makeAlias) const +PickKnobDialog::getSelectedKnob(bool* makeAlias,boost::shared_ptr* page,boost::shared_ptr* group) const { QString index = _imp->nodeSelectionCombo->text(); boost::shared_ptr selectedNode; @@ -228,6 +338,8 @@ PickKnobDialog::getSelectedKnob(bool* makeAlias) const bool hadPanelVisible = selectedPanel && !selectedPanel->isClosed(); if (!selectedPanel) { selectedNodeGui->ensurePanelCreated(); + selectedPanel = selectedNodeGui->getSettingPanel(); + selectedNodeGui->setVisibleSettingsPanel(false); } if (!selectedPanel) { return 0; @@ -235,11 +347,22 @@ PickKnobDialog::getSelectedKnob(bool* makeAlias) const if (!hadPanelVisible && selectedPanel) { selectedPanel->setClosed(true); } + + + int page_i = _imp->destPageCombo->activeIndex(); + if (page_i >= 0 && page_i < (int)_imp->pages.size()) { + *page = _imp->pages[page_i]; + } + + *group = _imp->getSelectedGroup(); + const std::map,KnobGui*>& knobsMap = selectedPanel->getKnobs(); std::map,KnobGui*>::const_iterator found = knobsMap.find(selectedKnob); if (found != knobsMap.end()) { *makeAlias = _imp->useAliasCheckBox->isChecked(); return found->second; } + + return 0; } diff --git a/Gui/PickKnobDialog.h b/Gui/PickKnobDialog.h index e71a20aa9e..1cfa303395 100644 --- a/Gui/PickKnobDialog.h +++ b/Gui/PickKnobDialog.h @@ -29,16 +29,20 @@ #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include +#include #endif +CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include +CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -class DockablePanel; -class KnobGui; +#include "Gui/GuiFwd.h" + struct PickKnobDialogPrivate; + class PickKnobDialog : public QDialog { Q_OBJECT @@ -49,11 +53,12 @@ class PickKnobDialog : public QDialog virtual ~PickKnobDialog(); - KnobGui* getSelectedKnob(bool* makeAlias) const; + KnobGui* getSelectedKnob(bool* makeAlias,boost::shared_ptr* page, boost::shared_ptr* group) const; public Q_SLOTS: void onNodeComboEditingFinished(); + void onPageComboIndexChanged(int index); private: diff --git a/Gui/PreferencesPanel.h b/Gui/PreferencesPanel.h index 4be60fa530..d96fbd97cb 100644 --- a/Gui/PreferencesPanel.h +++ b/Gui/PreferencesPanel.h @@ -25,26 +25,21 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" +#include "Gui/GuiFwd.h" + -class Settings; -class DockablePanel; -class QVBoxLayout; -//class QHBoxLayout; -class QDialogButtonBox; -class Button; -class KnobI; -class Gui; class PreferencesPanel : public QWidget { diff --git a/Gui/ProjectGui.h b/Gui/ProjectGui.h index aca4e0e6c8..be7e2dcd61 100644 --- a/Gui/ProjectGui.h +++ b/Gui/ProjectGui.h @@ -41,30 +41,8 @@ CLANG_DIAG_ON(uninitialized) #include "Engine/Format.h" -class Button; -class QWidget; -class QHBoxLayout; -class QVBoxLayout; -class ComboBox; -class SpinBox; -class LineEdit; -class KnobColor; -class DockablePanel; -class ProjectGuiSerialization; -class Gui; -class NodeGui; -class ViewerInstance; -class NodeGuiSerialization; -namespace boost { -namespace archive { -class xml_archive; -} -} - -namespace Natron { -class Project; -class Label; -} +#include "Gui/GuiFwd.h" + class ProjectGui : public QObject diff --git a/Gui/ProjectGuiSerialization.h b/Gui/ProjectGuiSerialization.h index 10e21c7c36..102889ce68 100644 --- a/Gui/ProjectGuiSerialization.h +++ b/Gui/ProjectGuiSerialization.h @@ -25,9 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include -#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_OFF GCC_DIAG_OFF(unused-parameter) @@ -47,6 +49,8 @@ GCC_DIAG_ON(unused-parameter) #include "Gui/NodeGuiSerialization.h" #include "Gui/NodeBackDropSerialization.h" +#include "Gui/GuiFwd.h" + #define PYTHON_PANEL_SERIALIZATION_VERSION 1 @@ -87,11 +91,6 @@ GCC_DIAG_ON(unused-parameter) #define kNatronProjectSettingsPanelSerializationName "Natron_Project_Settings_Panel" -class ProjectGui; -class Gui; -class Splitter; -class TabWidget; -class PyPanel; struct ViewerData { diff --git a/Gui/PropertiesBinWrapper.h b/Gui/PropertiesBinWrapper.h index 12cf57d2be..70115ce453 100644 --- a/Gui/PropertiesBinWrapper.h +++ b/Gui/PropertiesBinWrapper.h @@ -25,8 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" #include "Gui/PanelWidget.h" +#include "Gui/GuiFwd.h" + class PropertiesBinWrapper : public QWidget, public PanelWidget { diff --git a/Gui/PythonPanels.h b/Gui/PythonPanels.h index b32eda5c3a..d48881e4f6 100644 --- a/Gui/PythonPanels.h +++ b/Gui/PythonPanels.h @@ -16,30 +16,30 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef PYTHONPANELS_H #define PYTHONPANELS_H +// ***** BEGIN PYTHON BLOCK ***** +// from : +// "Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included." #include +// ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" - #include "Engine/NodeWrapper.h" #include "Engine/ScriptObject.h" #include "Engine/Knob.h" + #include "Gui/PanelWidget.h" +#include "Gui/GuiFwd.h" -class GuiApp; -class Gui; -class TabWidget; -class Param; struct DialogParamHolderPrivate; class DialogParamHolder : public NamedKnobHolder diff --git a/Gui/QtDecoder.h b/Gui/QtDecoder.h index 959acbe93b..73b668524c 100644 --- a/Gui/QtDecoder.h +++ b/Gui/QtDecoder.h @@ -25,10 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include -#include "Global/Macros.h" CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -36,16 +37,9 @@ CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Engine/EffectInstance.h" +#include "Engine/EngineFwd.h" -namespace Natron { -namespace Color { -class Lut; -} -} -class KnobFile; -class KnobChoice; -class KnobInt; class QtReader : public Natron::EffectInstance { diff --git a/Gui/QtEncoder.h b/Gui/QtEncoder.h index 8a1b521853..50692b22ba 100644 --- a/Gui/QtEncoder.h +++ b/Gui/QtEncoder.h @@ -25,19 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include "Engine/OutputEffectInstance.h" +#include "Engine/EngineFwd.h" -namespace Natron { -namespace Color { -class Lut; -} -} - -class KnobOutputFile; -class KnobChoice; -class KnobButton; -class KnobInt; -class KnobBool; class QtWriter : public Natron::OutputEffectInstance diff --git a/Gui/QtEnumConvert.h b/Gui/QtEnumConvert.h index 5cc5bb69c6..4b81ed45c0 100644 --- a/Gui/QtEnumConvert.h +++ b/Gui/QtEnumConvert.h @@ -25,9 +25,10 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include -#include "Global/Macros.h" CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -38,6 +39,9 @@ CLANG_DIAG_ON(uninitialized) #include "Global/KeySymbols.h" #include "Global/Enums.h" +#include "Gui/GuiFwd.h" + + class QtEnumConvert { public: diff --git a/Gui/RegisteredTabs.h b/Gui/RegisteredTabs.h index 277da1bcb2..b755b36024 100644 --- a/Gui/RegisteredTabs.h +++ b/Gui/RegisteredTabs.h @@ -25,12 +25,14 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include // pair #include #include -class ScriptObject; -class PanelWidget; +#include "Gui/GuiFwd.h" + typedef std::map > RegisteredTabs; diff --git a/Gui/RenderStatsDialog.h b/Gui/RenderStatsDialog.h index 444b7cfbdc..78793e364e 100644 --- a/Gui/RenderStatsDialog.h +++ b/Gui/RenderStatsDialog.h @@ -25,24 +25,27 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) #include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) #include "Engine/RenderStats.h" +#include "Engine/EngineFwd.h" -namespace Natron { - class Node; -} +#include "Gui/GuiFwd.h" -class TableItem; -class Gui; -class QItemSelection; struct RenderStatsDialogPrivate; + class RenderStatsDialog : public QWidget { GCC_DIAG_SUGGEST_OVERRIDE_OFF diff --git a/Gui/RenderingProgressDialog.cpp b/Gui/RenderingProgressDialog.cpp index 7e487058fc..c6a5f567ed 100644 --- a/Gui/RenderingProgressDialog.cpp +++ b/Gui/RenderingProgressDialog.cpp @@ -36,7 +36,7 @@ CLANG_DIAG_OFF(uninitialized) #include #include #include -#include +#include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) diff --git a/Gui/RenderingProgressDialog.h b/Gui/RenderingProgressDialog.h index 8712e222b3..ef61456130 100644 --- a/Gui/RenderingProgressDialog.h +++ b/Gui/RenderingProgressDialog.h @@ -25,26 +25,23 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -class QVBoxLayout; -class QTextBrowser; -class Button; -class QString; -class ProcessHandler; +#include "Gui/GuiFwd.h" + + struct RenderingProgressDialogPrivate; -class Gui; class RenderingProgressDialog : public QDialog diff --git a/Gui/ResizableMessageBox.h b/Gui/ResizableMessageBox.h index 56e5d24516..e2e9cb9236 100644 --- a/Gui/ResizableMessageBox.h +++ b/Gui/ResizableMessageBox.h @@ -25,9 +25,16 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) #include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + +#include "Gui/GuiFwd.h" -#include "Global/Macros.h" // resizable message box, // see http://www.qtcentre.org/threads/24888-Resizing-a-QMessageBox#post135851 diff --git a/Gui/RightClickableWidget.h b/Gui/RightClickableWidget.h index 01e965858f..fa078ce12c 100644 --- a/Gui/RightClickableWidget.h +++ b/Gui/RightClickableWidget.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) @@ -33,8 +35,6 @@ #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -47,22 +47,8 @@ CLANG_DIAG_ON(uninitialized) #include "Engine/DockablePanelI.h" -class KnobI; -class KnobGui; -class KnobHolder; -class NodeGui; -class Gui; -class KnobPage; -class QVBoxLayout; -class Button; -class QUndoStack; -class QUndoCommand; -class QGridLayout; -class RotoPanel; -class MultiInstancePanel; -class QTabWidget; -class KnobGroup; -class DockablePanel; +#include "Gui/GuiFwd.h" + class RightClickableWidget : public QWidget { diff --git a/Gui/RotoGui.cpp b/Gui/RotoGui.cpp index 4b0fc896ed..4465ae4480 100644 --- a/Gui/RotoGui.cpp +++ b/Gui/RotoGui.cpp @@ -153,8 +153,9 @@ enum SelectedCpsTransformModeEnum ///A small structure of all the data shared by all the viewers watching the same Roto -struct RotoGuiSharedData +class RotoGuiSharedData { +public: SelectedItems selectedItems; SelectedCPs selectedCps; QRectF selectedCpsBbox; @@ -2715,7 +2716,6 @@ RotoGui::penDown(double time, */ _imp->checkViewersAreDirectlyConnected(); - _imp->context->getNode()->getApp()->setUserIsPainting(_imp->context->getNode()); if (_imp->rotoData->strokeBeingPaint && _imp->rotoData->strokeBeingPaint->getParentLayer() && _imp->multiStrokeEnabled->isChecked()) { @@ -2730,7 +2730,9 @@ RotoGui::penDown(double time, assert(layer); _imp->context->addItem(layer, 0, _imp->rotoData->strokeBeingPaint, RotoItem::eSelectionReasonOther); } - _imp->context->setStrokeBeingPainted(_imp->rotoData->strokeBeingPaint); + + _imp->context->getNode()->getApp()->setUserIsPainting(_imp->context->getNode(),_imp->rotoData->strokeBeingPaint, true); + boost::shared_ptr lifeTimeFrameKnob = _imp->rotoData->strokeBeingPaint->getLifeTimeFrameKnob(); lifeTimeFrameKnob->setValue(_imp->context->getTimelineCurrentTime(), 0); @@ -3272,7 +3274,7 @@ RotoGui::penUp(double /*time*/, if (_imp->state == eEventStateBuildingStroke) { assert(_imp->rotoData->strokeBeingPaint); - _imp->context->getNode()->getApp()->setUserIsPainting(boost::shared_ptr()); + _imp->context->getNode()->getApp()->setUserIsPainting(_imp->context->getNode(),_imp->rotoData->strokeBeingPaint, false); assert(_imp->rotoData->strokeBeingPaint->getParentLayer()); _imp->rotoData->strokeBeingPaint->setStrokeFinished(); if (!_imp->multiStrokeEnabled->isChecked()) { @@ -3504,7 +3506,7 @@ RotoGui::RotoGuiPrivate::makeStroke(bool prepareForLater, const RotoPoint& p) } assert(layer); context->addItem(layer, 0, rotoData->strokeBeingPaint, RotoItem::eSelectionReasonOther); - context->setStrokeBeingPainted(rotoData->strokeBeingPaint); + context->getNode()->getApp()->setUserIsPainting(context->getNode(),rotoData->strokeBeingPaint, true); rotoData->strokeBeingPaint->appendPoint(true,p); } diff --git a/Gui/RotoGui.h b/Gui/RotoGui.h index 7dff37bb94..50ec15d006 100644 --- a/Gui/RotoGui.h +++ b/Gui/RotoGui.h @@ -25,11 +25,13 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -39,26 +41,10 @@ CLANG_DIAG_ON(uninitialized) #include "Global/GlobalDefines.h" -class QInputEvent; -class QMouseEvent; -class QToolBar; -class QWidget; -class QIcon; -class QString; -class QToolButton; -class QKeyEvent; -class QPointF; -class ViewerTab; -class QAction; -class RotoItem; -class QUndoCommand; -class NodeGui; -class Bezier; -class RotoDrawableItem; -class BezierCP; -class GuiAppInstance; -struct RotoGuiSharedData; -class RotoContext; +#include "Engine/EngineFwd.h" + +#include "Gui/GuiFwd.h" + class RotoToolButton : public QToolButton diff --git a/Gui/RotoPanel.h b/Gui/RotoPanel.h index 35d6d5929d..a3a2a30fac 100644 --- a/Gui/RotoPanel.h +++ b/Gui/RotoPanel.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef ROTOPANEL_H #define ROTOPANEL_H @@ -26,12 +25,14 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #include #endif -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -40,15 +41,11 @@ CLANG_DIAG_ON(uninitialized) #include "Global/GlobalDefines.h" -class QTreeWidgetItem; -class QWidget; -class NodeGui; -class QUndoCommand; -class RotoItem; -class RotoContext; -class RotoLayer; -class RotoDrawableItem; +#include "Gui/GuiFwd.h" + + struct RotoPanelPrivate; + class RotoPanel : public QWidget { @@ -188,8 +185,9 @@ public Q_SLOTS: }; -struct DroppedTreeItem +class DroppedTreeItem { +public: boost::shared_ptr newParentLayer; int insertIndex; QTreeWidgetItem* newParentItem; diff --git a/Gui/RotoUndoCommand.h b/Gui/RotoUndoCommand.h index 4722e7cc84..bd4cbd6f99 100644 --- a/Gui/RotoUndoCommand.h +++ b/Gui/RotoUndoCommand.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef ROTOUNDOCOMMAND_H #define ROTOUNDOCOMMAND_H @@ -26,31 +25,27 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include -#include -#include + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif -#include "Global/Macros.h" -class Bezier; -class BezierCP; -class RotoGui; -class RotoLayer; -class RotoPanel; -class QRectF; -class Curve; -class RotoDrawableItem; -class RotoStrokeItem; -class QTreeWidgetItem; -class RotoItem; -class KnobDouble; -namespace Transform { -struct Matrix3x3; -} -struct DroppedTreeItem; + +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) +#include +#include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + +#include "Engine/EngineFwd.h" + +#include "Gui/GuiFwd.h" + class MoveControlPointsUndoCommand : public QUndoCommand diff --git a/Gui/ScaleSliderQWidget.h b/Gui/ScaleSliderQWidget.h index 3173dd1860..0276f6e4fc 100644 --- a/Gui/ScaleSliderQWidget.h +++ b/Gui/ScaleSliderQWidget.h @@ -26,9 +26,11 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -37,12 +39,10 @@ CLANG_DIAG_ON(uninitialized) #include "Global/GlobalDefines.h" -using Natron::ScaleTypeEnum; +#include "Gui/GuiFwd.h" + struct ScaleSliderQWidgetPrivate; -class QColor; -class QFont; -class Gui; class ScaleSliderQWidget : public QWidget diff --git a/Gui/ScriptEditor.cpp b/Gui/ScriptEditor.cpp index bdc0cfd72a..0c972315f4 100644 --- a/Gui/ScriptEditor.cpp +++ b/Gui/ScriptEditor.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Gui/ScriptEditor.h b/Gui/ScriptEditor.h index 727d3804c1..2b4176247e 100644 --- a/Gui/ScriptEditor.h +++ b/Gui/ScriptEditor.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef SCRIPTEDITOR_H #define SCRIPTEDITOR_H @@ -26,12 +25,13 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif -#include "Global/Macros.h" CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -39,8 +39,8 @@ CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Gui/PanelWidget.h" +#include "Gui/GuiFwd.h" -class Gui; struct ScriptEditorPrivate; diff --git a/Gui/ScriptTextEdit.h b/Gui/ScriptTextEdit.h index 075b00078a..10348bb5d3 100644 --- a/Gui/ScriptTextEdit.h +++ b/Gui/ScriptTextEdit.h @@ -15,6 +15,7 @@ * You should have received a copy of the GNU General Public License * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ + #ifndef SCRIPTTEXTEDIT_H #define SCRIPTTEXTEDIT_H @@ -25,6 +26,13 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + +#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) +#include +#include +#include +#endif + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -32,15 +40,12 @@ CLANG_DIAG_OFF(uninitialized) #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) -#include -#include -#include -#endif +#include "Gui/GuiFwd.h" struct PySyntaxHighlighterPrivate; + class PySyntaxHighlighter : public QSyntaxHighlighter { diff --git a/Gui/SequenceFileDialog.h b/Gui/SequenceFileDialog.h index fe648e0be1..d5948b53b7 100644 --- a/Gui/SequenceFileDialog.h +++ b/Gui/SequenceFileDialog.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include #include @@ -37,8 +39,6 @@ #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -57,35 +57,11 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" #include "Global/QtCompat.h" -#include "Engine/FileSystemModel.h" - - -class LineEdit; -class Button; -class QCheckBox; -class ComboBox; -class QWidget; -namespace Natron { -class Label; -} -class QFileInfo; -class QHBoxLayout; -class QVBoxLayout; -class QSplitter; -class QAction; -class SequenceFileDialog; -class QFileSystemModel; -class SequenceItemDelegate; -class Gui; -class NodeGui; -namespace SequenceParsing { -class SequenceFromFiles; -} -struct FileDialogPreviewProvider; +#include "Engine/FileSystemModel.h" +#include "Gui/GuiFwd.h" /** diff --git a/Gui/SerializableWindow.h b/Gui/SerializableWindow.h index 0c72f44037..b9f0c71984 100644 --- a/Gui/SerializableWindow.h +++ b/Gui/SerializableWindow.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef SERIALIZABLEWINDOW_H #define SERIALIZABLEWINDOW_H @@ -26,7 +25,11 @@ #include // ***** END PYTHON BLOCK ***** -class QMutex; +#include "Global/Macros.h" + +#include "Engine/EngineFwd.h" + +#include "Gui/GuiFwd.h" /** diff --git a/Gui/Shaders.h b/Gui/Shaders.h index 525844c2a9..0c5b41a16f 100644 --- a/Gui/Shaders.h +++ b/Gui/Shaders.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef Natron_shaders_h #define Natron_shaders_h diff --git a/Gui/ShortCutEditor.h b/Gui/ShortCutEditor.h index c021b8f749..21e504e19d 100644 --- a/Gui/ShortCutEditor.h +++ b/Gui/ShortCutEditor.h @@ -26,6 +26,7 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) GCC_DIAG_UNUSED_LOCAL_TYPEDEFS_OFF // /opt/boost/include/boost/serialization/static_warning.hpp:104:18: warning: typedef 'STATIC_WARNING_LINE102' locally defined but not used [-Wunused-local-typedefs] @@ -42,9 +43,11 @@ CLANG_DIAG_ON(uninitialized) CLANG_DIAG_ON(deprecated-register) #include "Gui/LineEdit.h" +#include "Gui/GuiFwd.h" + -class BoundAction; struct ShortCutEditorPrivate; + class ShortCutEditor : public QWidget { diff --git a/Gui/SpinBox.h b/Gui/SpinBox.h index 5ab6fea4af..79cfe8aa80 100644 --- a/Gui/SpinBox.h +++ b/Gui/SpinBox.h @@ -25,17 +25,18 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif + #include "Gui/LineEdit.h" +#include "Gui/GuiFwd.h" -class KnobGui; -class QColor; -class QMenu; -class SpinBoxValidator; struct SpinBoxPrivate; + class SpinBox : public LineEdit { diff --git a/Gui/SpinBoxValidator.h b/Gui/SpinBoxValidator.h index 763424897e..eaf4fd65b3 100644 --- a/Gui/SpinBoxValidator.h +++ b/Gui/SpinBoxValidator.h @@ -25,17 +25,17 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #include #endif -#include "Global/Macros.h" +#include "Gui/GuiFwd.h" + -class SpinBox; -class KnobGui; -class QString; class SpinBoxValidator { public: diff --git a/Gui/SplashScreen.h b/Gui/SplashScreen.h index e9ec25587d..24103aef61 100644 --- a/Gui/SplashScreen.h +++ b/Gui/SplashScreen.h @@ -26,6 +26,7 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -34,6 +35,9 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) +#include "Gui/GuiFwd.h" + + class SplashScreen : public QWidget { diff --git a/Gui/Splitter.h b/Gui/Splitter.h index 31e22f07d5..c4d73fd793 100644 --- a/Gui/Splitter.h +++ b/Gui/Splitter.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef SPLITTER_H #define SPLITTER_H @@ -26,8 +25,10 @@ #include // ***** END PYTHON BLOCK ***** -#include #include "Global/Macros.h" + +#include + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -35,10 +36,12 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) +#include "Gui/GuiFwd.h" + + /** * @class A thread-safe wrapper over QSplitter **/ -class QString; class Splitter : public QSplitter { diff --git a/Gui/TabGroup.h b/Gui/TabGroup.h index 83bced1b1e..00b56cd3da 100644 --- a/Gui/TabGroup.h +++ b/Gui/TabGroup.h @@ -25,6 +25,8 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) @@ -33,8 +35,6 @@ #include #endif -#include "Global/Macros.h" - CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -47,21 +47,8 @@ CLANG_DIAG_ON(uninitialized) #include "Engine/DockablePanelI.h" -class KnobI; -class KnobGui; -class KnobHolder; -class NodeGui; -class Gui; -class KnobPage; -class QVBoxLayout; -class Button; -class QUndoStack; -class QUndoCommand; -class QGridLayout; -class RotoPanel; -class MultiInstancePanel; -class QTabWidget; -class KnobGroup; +#include "Gui/GuiFwd.h" + /** * @brief Used when group are using the kFnOfxParamPropGroupIsTab extension diff --git a/Gui/TabWidget.h b/Gui/TabWidget.h index 40a9f2f2f0..9bac776f72 100644 --- a/Gui/TabWidget.h +++ b/Gui/TabWidget.h @@ -25,16 +25,15 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include - #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif - -#include "Global/Macros.h" CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include @@ -43,25 +42,8 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#include "Global/Macros.h" +#include "Gui/GuiFwd.h" -class QWidget; -class QStyle; -class QHBoxLayout; -class QPushButton; -class QVBoxLayout; -class QMenu; -class Button; -class QMouseEvent; -class QDropEvent; -class QDragEnterEvent; -class QDragLeaveEvent; -class TabWidget; -class QPaintEvent; -class Gui; -class ScriptObject; -class Splitter; -class PanelWidget; class DragPixmap : public QWidget diff --git a/Gui/TableModelView.h b/Gui/TableModelView.h index 3296d4433d..6bc40a2820 100644 --- a/Gui/TableModelView.h +++ b/Gui/TableModelView.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef TABLEMODELVIEW_H #define TABLEMODELVIEW_H @@ -26,10 +25,11 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif -#include "Global/Macros.h" CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) @@ -39,8 +39,9 @@ CLANG_DIAG_OFF(uninitialized) CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -class TableView; -class TableModel; +#include "Gui/GuiFwd.h" + + class TableItem { friend class TableModel; diff --git a/Gui/TextRenderer.h b/Gui/TextRenderer.h index dc80ff9d95..b129c61499 100644 --- a/Gui/TextRenderer.h +++ b/Gui/TextRenderer.h @@ -25,12 +25,14 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif -class QString; -class QColor; -class QFont; + +#include "Gui/GuiFwd.h" + namespace Natron { class TextRenderer diff --git a/Gui/Texture.h b/Gui/Texture.h index f1804c55c4..20a10b073a 100644 --- a/Gui/Texture.h +++ b/Gui/Texture.h @@ -26,8 +26,12 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + #include "Global/GlobalDefines.h" + #include "Engine/TextureRect.h" +#include "Engine/EngineFwd.h" + class Texture { diff --git a/Gui/TimeLineGui.h b/Gui/TimeLineGui.h index b339d93b2a..3269eb0674 100644 --- a/Gui/TimeLineGui.h +++ b/Gui/TimeLineGui.h @@ -25,12 +25,15 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include "Global/GLIncludes.h" //!_menu); return _imp->_menu; + assert(_imp->_menu); + return _imp->_menu; } void @@ -144,13 +145,12 @@ void ToolButton::tryAddChild(ToolButton* child) { assert(_imp->_menu); - for (unsigned int i = 0; i < _imp->_children.size(); ++i) { - if (_imp->_children[i] == child) { - return; - } + // insert if not present + std::vector &children = _imp->_children; + if (std::find(children.begin(), children.end(), child) == children.end()) { + children.push_back(child); + _imp->_menu->addAction( child->getAction() ); } - _imp->_children.push_back(child); - _imp->_menu->addAction( child->getAction() ); } const std::vector & diff --git a/Gui/ToolButton.h b/Gui/ToolButton.h index 33e2d3724c..0ad3b51c00 100644 --- a/Gui/ToolButton.h +++ b/Gui/ToolButton.h @@ -26,23 +26,26 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + +#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) +#include +#include +#endif + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -#if !defined(Q_MOC_RUN) && !defined(SBK_RUN) -#include -#include -#endif -class PluginGroupNode; -class GuiAppInstance; -class QMenu; -class QAction; +#include "Engine/EngineFwd.h" + +#include "Gui/GuiFwd.h" + struct ToolButtonPrivate; + class ToolButton : public QObject { diff --git a/Gui/TrackerGui.h b/Gui/TrackerGui.h index 0ebb5e616c..54ddbe4107 100644 --- a/Gui/TrackerGui.h +++ b/Gui/TrackerGui.h @@ -16,7 +16,6 @@ * along with Natron. If not, see * ***** END LICENSE BLOCK ***** */ - #ifndef TRACKERGUI_H #define TRACKERGUI_H @@ -26,26 +25,24 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #include #endif -#include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) -class QWidget; -class ViewerTab; -class TrackerPanel; -class QKeyEvent; -class QPointF; -class QMouseEvent; -class QInputEvent; +#include "Gui/GuiFwd.h" + struct TrackerGuiPrivate; + class TrackerGui : public QObject { diff --git a/Gui/Utils.h b/Gui/Utils.h index 28c694165d..773c372a8b 100644 --- a/Gui/Utils.h +++ b/Gui/Utils.h @@ -25,7 +25,16 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) #include // for Qt::WhiteSpaceMode +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + +#include "Gui/GuiFwd.h" + namespace Natron { QString convertFromPlainText(const QString &plain, Qt::WhiteSpaceMode mode); diff --git a/Gui/VerticalColorBar.h b/Gui/VerticalColorBar.h index caeb6a4ef2..550f142125 100644 --- a/Gui/VerticalColorBar.h +++ b/Gui/VerticalColorBar.h @@ -25,14 +25,18 @@ #include // ***** END PYTHON BLOCK ***** - #include "Global/Macros.h" +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) #include #include #include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) + +#include "Gui/GuiFwd.h" -class QPaintEvent; class VerticalColorBar : public QWidget { diff --git a/Gui/ViewerGL.cpp b/Gui/ViewerGL.cpp index f738f8ea56..a467b985aa 100644 --- a/Gui/ViewerGL.cpp +++ b/Gui/ViewerGL.cpp @@ -2635,6 +2635,8 @@ ViewerGL::fitImageToFormat(bool useProjectFormat) } _imp->viewerTab->getInternalNode()->renderCurrentFrame(false); + + update(); } /** @@ -3450,7 +3452,13 @@ ViewerGL::updateInfoWidgetColorPicker(const QPointF & imgPos, { Format dispW = getDisplayWindow(); RectD canonicalDispW = dispW.toCanonicalFormat(); - if (!_imp->viewerTab->getGui()->getApp()->getIsUserPainting().get()) { + + NodePtr rotoPaintNode; + boost::shared_ptr curStroke; + bool isDrawing; + _imp->viewerTab->getGui()->getApp()->getActiveRotoDrawingStroke(&rotoPaintNode, &curStroke, &isDrawing); + + if (!isDrawing) { for (int i = 0; i < 2; ++i) { const RectD& rod = getRoD(i); updateInfoWidgetColorPickerInternal(imgPos, widgetPos, width(), height(), rod, canonicalDispW, i); diff --git a/Gui/ViewerGL.h b/Gui/ViewerGL.h index b921282ce1..3f09735cf6 100644 --- a/Gui/ViewerGL.h +++ b/Gui/ViewerGL.h @@ -25,39 +25,28 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include #if !defined(Q_MOC_RUN) && !defined(SBK_RUN) #include #endif -#include "Global/Macros.h" + +#include "Global/GLIncludes.h" //! CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) #include "Engine/OpenGLViewerI.h" -#include "Global/Macros.h" +#include "Engine/EngineFwd.h" + +#include "Gui/GuiFwd.h" + -class QKeyEvent; -class QEvent; -class QMenu; -class QGLShaderProgram; - -namespace Natron { -class ChannelSet; -class Image; -} -class InfoViewerWidget; -class AppInstance; -class ViewerInstance; -class ViewerTab; -class ImageInfo; -class QInputEvent; -struct TextureRect; -class Format; /** *@class ViewerGL diff --git a/Gui/ViewerGLPrivate.h b/Gui/ViewerGLPrivate.h index f610145164..e4a29100f2 100644 --- a/Gui/ViewerGLPrivate.h +++ b/Gui/ViewerGLPrivate.h @@ -26,7 +26,12 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) #include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) #include "Engine/Image.h" #include "Engine/ImageInfo.h" @@ -34,8 +39,8 @@ #include "Gui/TextRenderer.h" #include "Gui/ViewerGL.h" #include "Gui/ZoomContext.h" +#include "Gui/GuiFwd.h" -class Texture; #define WIPE_MIX_HANDLE_LENGTH 50. #define WIPE_ROTATE_HANDLE_LENGTH 100. diff --git a/Gui/ViewerTab.h b/Gui/ViewerTab.h index c1bea14943..bdc4676f77 100644 --- a/Gui/ViewerTab.h +++ b/Gui/ViewerTab.h @@ -36,28 +36,14 @@ #include "Global/KeySymbols.h" // Key #include "Engine/RenderStats.h" +#include "Engine/EngineFwd.h" #include "Gui/PanelWidget.h" +#include "Gui/GuiFwd.h" + -namespace Natron -{ - class Node; - class ImageComponents; -} typedef std::map,NodeRenderStats > RenderStatsMap; -class ViewerGL; -class ViewerInstance; -class Gui; -class RectD; -class Format; -class QMouseEvent; -class RotoGui; -class NodeGui; -class TimeLine; -class TrackerGui; -class QInputEvent; -struct RotoGuiSharedData; struct ViewerTabPrivate; class ViewerTab : public QWidget, public PanelWidget { diff --git a/Gui/ViewerTab10.cpp b/Gui/ViewerTab10.cpp index 076ea82848..159c8dbddb 100644 --- a/Gui/ViewerTab10.cpp +++ b/Gui/ViewerTab10.cpp @@ -685,7 +685,7 @@ ViewerTab::keyPressEvent(QKeyEvent* e) _imp->renderScaleCombo->setCurrentIndex(4); } else if (isKeybind(kShortcutGroupViewer, kShortcutIDActionZoomLevel100, modifiers, key) ) { _imp->viewer->zoomSlot(100); - _imp->zoomCombobox->setCurrentIndex_no_emit(4); + _imp->zoomCombobox->setCurrentIndex_no_emit(7); } else if (isKeybind(kShortcutGroupViewer, kShortcutIDActionZoomIn, modifiers, key) ) { zoomIn(); } else if (isKeybind(kShortcutGroupViewer, kShortcutIDActionZoomOut, modifiers, key) ) { @@ -748,7 +748,9 @@ ViewerTab::keyPressEvent(QKeyEvent* e) update(); } else if (isKeybind(kShortcutGroupViewer, kShortcutIDSwitchInputAAndB, modifiers, key) ) { ///Put it after notifyOverlaysKeyDown() because Roto may intercept Enter - switchInputAAndB(); + if (getViewer()->hasFocus()) { + switchInputAAndB(); + } } else if (isKeybind(kShortcutGroupViewer, kShortcutIDShowLeftView, modifiers, key) ) { showView(0); } else if (isKeybind(kShortcutGroupViewer, kShortcutIDShowRightView, modifiers, key) ) { diff --git a/Gui/ViewerTab20.cpp b/Gui/ViewerTab20.cpp index ac1aa1be62..375f54b4c2 100644 --- a/Gui/ViewerTab20.cpp +++ b/Gui/ViewerTab20.cpp @@ -73,12 +73,17 @@ ViewerTab::drawOverlays(double time, double scaleY) const { + boost::shared_ptr rotoPaintNode; + boost::shared_ptr curStroke; + bool isDrawing; + getGui()->getApp()->getActiveRotoDrawingStroke(&rotoPaintNode, &curStroke,&isDrawing); + if (!getGui() || !getGui()->getApp() || !_imp->viewer || getGui()->getApp()->isClosing() || isFileDialogViewer() || - (getGui()->isGUIFrozen() && !getGui()->getApp()->getIsUserPainting()) || + (getGui()->isGUIFrozen() && !isDrawing) || getGui()->getApp()->isShowingDialog()) { return; } diff --git a/Gui/ViewerTabPrivate.h b/Gui/ViewerTabPrivate.h index 7181af1c54..2e800e42b8 100644 --- a/Gui/ViewerTabPrivate.h +++ b/Gui/ViewerTabPrivate.h @@ -25,55 +25,28 @@ #include // ***** END PYTHON BLOCK ***** +#include "Global/Macros.h" + #include #include -#include "Global/Macros.h" - +CLANG_DIAG_OFF(deprecated) +CLANG_DIAG_OFF(uninitialized) #include +CLANG_DIAG_ON(deprecated) +CLANG_DIAG_ON(uninitialized) #include "Global/Enums.h" +#include "Engine/EngineFwd.h" + #include "Gui/ComboBox.h" +#include "Gui/GuiFwd.h" -class QWidget; -class QHBoxLayout; -class QVBoxLayout; -class QCheckBox; - -namespace Natron { - class Node; - class Label; - class ClickableLabel; - class EffectInstance; - class ImageComponents; -} -class ViewerGL; -class ViewerTab; -class GuiAppInstance; -class ComboBox; -class Button; -class SpinBox; -class ChannelsComboBox; -class ScaleSliderQWidget; -class InfoViewerWidget; -class LineEdit; -class TimeLineGui; -namespace Transform { - struct Matrix3x3; -} -class Gui; -class ViewerInstance; -class NodeGui; -class RotoGui; -class TrackerGui; #define NATRON_TRANSFORM_AFFECTS_OVERLAYS -using namespace Natron; - - struct ViewerTabPrivate { struct InputName @@ -165,11 +138,11 @@ struct ViewerTabPrivate LineEdit* frameRangeEdit; - ClickableLabel* canEditFrameRangeLabel; + Natron::ClickableLabel* canEditFrameRangeLabel; Button* tripleSyncButton; QCheckBox* canEditFpsBox; - ClickableLabel* canEditFpsLabel; + Natron::ClickableLabel* canEditFpsLabel; mutable QMutex fpsLockedMutex; bool fpsLocked; SpinBox* fpsBox; @@ -184,7 +157,7 @@ struct ViewerTabPrivate std::pair currentTracker; InputNamesMap inputNamesMap; mutable QMutex compOperatorMutex; - ViewerCompositingOperatorEnum compOperator; + Natron::ViewerCompositingOperatorEnum compOperator; ViewerInstance* viewerNode; // < pointer to the internal node mutable QMutex visibleToolbarsMutex; //< protects the 4 bool below @@ -226,7 +199,7 @@ struct ViewerTabPrivate #endif - void getComponentsAvailabel(std::set* comps) const; + void getComponentsAvailabel(std::set* comps) const; }; #endif // Gui_ViewerTabPrivate_h diff --git a/Gui/ZoomContext.h b/Gui/ZoomContext.h index bc7466ced5..ea46c063f3 100644 --- a/Gui/ZoomContext.h +++ b/Gui/ZoomContext.h @@ -26,12 +26,16 @@ // ***** END PYTHON BLOCK ***** #include "Global/Macros.h" + CLANG_DIAG_OFF(deprecated) CLANG_DIAG_OFF(uninitialized) #include CLANG_DIAG_ON(deprecated) CLANG_DIAG_ON(uninitialized) +#include "Gui/GuiFwd.h" + + /** *@class ZoomContext *@brief Holds all zoom related variables. This is an internal class used by the ViewerGL. diff --git a/Tests/BaseTest.h b/Tests/BaseTest.h index 90fdf509e9..aaff059b69 100644 --- a/Tests/BaseTest.h +++ b/Tests/BaseTest.h @@ -36,11 +36,8 @@ CLANG_DIAG_OFF(deprecated) #include CLANG_DIAG_ON(deprecated) -class AppInstance; +#include "Engine/EngineFwd.h" -namespace Natron { -class Node; -} class BaseTest : public testing::Test diff --git a/tools/MacOSX/ports/aqua/qt4-mac/Portfile b/tools/MacOSX/ports/aqua/qt4-mac/Portfile index ea3477b1de..76c4dc3958 100644 --- a/tools/MacOSX/ports/aqua/qt4-mac/Portfile +++ b/tools/MacOSX/ports/aqua/qt4-mac/Portfile @@ -1,5 +1,5 @@ # -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 -# $Id: Portfile 141286 2015-10-14 17:53:19Z michaelld@macports.org $ +# $Id: Portfile 142934 2015-11-28 18:06:52Z mcalhoun@macports.org $ PortSystem 1.0 @@ -14,7 +14,7 @@ name qt4-mac # qt4-mac-devel is "replaced_by" this port, # so this port cannot conflict with it. #conflicts qt3 qt3-mac qt4-mac-devel -conflicts qt3 qt3-mac qt5-mac +conflicts qt3 qt3-mac version 4.8.7 revision 102 set branch [join [lrange [split ${version} .] 0 1] .] diff --git a/tools/MacOSX/ports/aqua/qt4-mac/Portfile.orig b/tools/MacOSX/ports/aqua/qt4-mac/Portfile.orig index a5b65d688b..cf91e2ec07 100644 --- a/tools/MacOSX/ports/aqua/qt4-mac/Portfile.orig +++ b/tools/MacOSX/ports/aqua/qt4-mac/Portfile.orig @@ -1,5 +1,5 @@ # -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 -# $Id: Portfile 141286 2015-10-14 17:53:19Z michaelld@macports.org $ +# $Id: Portfile 142934 2015-11-28 18:06:52Z mcalhoun@macports.org $ PortSystem 1.0 @@ -14,7 +14,7 @@ name qt4-mac # qt4-mac-devel is "replaced_by" this port, # so this port cannot conflict with it. #conflicts qt3 qt3-mac qt4-mac-devel -conflicts qt3 qt3-mac qt5-mac +conflicts qt3 qt3-mac version 4.8.7 revision 2 set branch [join [lrange [split ${version} .] 0 1] .] diff --git a/tools/MacOSX/ports/aqua/qt4-mac/Portfile.patch b/tools/MacOSX/ports/aqua/qt4-mac/Portfile.patch index 994ee89f74..0004e01bb5 100644 --- a/tools/MacOSX/ports/aqua/qt4-mac/Portfile.patch +++ b/tools/MacOSX/ports/aqua/qt4-mac/Portfile.patch @@ -1,8 +1,8 @@ ---- Portfile.orig 2015-11-24 12:21:32.000000000 +0100 -+++ Portfile 2015-11-24 12:22:39.000000000 +0100 +--- Portfile.orig 2015-12-01 09:10:35.000000000 +0100 ++++ Portfile 2015-12-01 09:10:47.000000000 +0100 @@ -16,7 +16,7 @@ #conflicts qt3 qt3-mac qt4-mac-devel - conflicts qt3 qt3-mac qt5-mac + conflicts qt3 qt3-mac version 4.8.7 -revision 2 +revision 102 diff --git a/tools/MacOSX/ports/devel/cmake/Portfile b/tools/MacOSX/ports/devel/cmake/Portfile index 7b5bcdb883..5b87a9ae90 100644 --- a/tools/MacOSX/ports/devel/cmake/Portfile +++ b/tools/MacOSX/ports/devel/cmake/Portfile @@ -1,5 +1,5 @@ # -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 -# $Id: Portfile 142106 2015-11-03 18:30:17Z michaelld@macports.org $ +# $Id: Portfile 142646 2015-11-18 15:01:12Z michaelld@macports.org $ PortSystem 1.0 universal_variant no @@ -23,16 +23,15 @@ dist_subdir cmake subport cmake-devel {} -set branch 3.3 +set branch 3.4 if {${subport} eq ${name}} { # release - version ${branch}.2 - revision 1 - checksums rmd160 c7d3b8895e2e143b7e1019477764370535917dca \ - sha256 e75a178d6ebf182b048ebfe6e0657c49f0dc109779170bad7ffcb17463f2fc22 + version ${branch}.0 + checksums rmd160 95d3d0cd86e17c249459975eb9b293a5075ae87a \ + sha256 a5b82bf6ace6c481cdb911fd5d372a302740cbefd387e05297cb37f7468d1cea long_description ${base_long_description} \ The ${subport} release port is updated roughly every few months. @@ -41,13 +40,6 @@ if {${subport} eq ${name}} { master_sites http://www.cmake.org/files/v${branch}/ - patchfiles-append patch-Modules-noArchCheck.release.diff - - # temporary patch to find Boost 1.59; - # remove when updating to next release - - patchfiles-append patch-Modules-FindBoost.cmake.diff - livecheck.type regex livecheck.regex ${name}-(\[0-9.\]+)${extract.suffix} livecheck.url [lindex $master_sites 0] @@ -55,12 +47,12 @@ if {${subport} eq ${name}} { } else { # devel - version 20151102 + version 20151116 set dist_branch 3.4 - set dist_date 20151102 - set dist_hash g7b24b - checksums rmd160 f0aa044cc36f29eb5f962e4fc36660c9d29e7011 \ - sha256 42a24505a5927d5d37bbc79fb05d2fc4355d261b0502282639761144a45cb197 + set dist_date 20151116 + set dist_hash g89134 + checksums rmd160 6140db936ca93e0718d58694cdf8651c783cb907 \ + sha256 60cccf1952cc3faf9e7e3312ac9b7239b06cb22f0a4e24bef89b3fc901ae5474 master_sites http://www.cmake.org/files/dev/ distname ${name}-${dist_branch}.${dist_date}-${dist_hash} @@ -69,8 +61,6 @@ if {${subport} eq ${name}} { long_description ${base_long_description} \ The ${subport} port is updated roughly every week. - patchfiles-append patch-Modules-noArchCheck.devel.diff - livecheck.type regex livecheck.regex (${name}-\[0-9a-g.-\]+)${extract.suffix} livecheck.version ${distname} @@ -82,7 +72,8 @@ depends_lib-append port:curl \ port:expat \ port:zlib \ port:bzip2 \ - port:libarchive + port:libarchive \ + port:ncurses # CMake 3.2 changed dependency requirements to include jsoncpp. # jsoncpp 1.0+ requires CMake for building. catch 22. So, have CMake @@ -92,7 +83,8 @@ patchfiles-append patch-CMakeFindFrameworks.cmake.diff \ patch-Modules-FindFreetype.cmake.diff \ patch-Modules-FindQt4.cmake.diff \ patch-Modules-Platform-Darwin.cmake.diff \ - patch-Modules-Platform-Darwin-Initialize.cmake.diff + patch-Modules-Platform-Darwin-Initialize.cmake.diff \ + patch-Modules-noArchCheck.diff configure.env-append \ CMAKE_PREFIX_PATH=${prefix} \ diff --git a/tools/MacOSX/ports/devel/cmake/Portfile.orig b/tools/MacOSX/ports/devel/cmake/Portfile.orig index 6cc66b31ad..7c7f83bc84 100644 --- a/tools/MacOSX/ports/devel/cmake/Portfile.orig +++ b/tools/MacOSX/ports/devel/cmake/Portfile.orig @@ -1,5 +1,5 @@ # -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 -# $Id: Portfile 142106 2015-11-03 18:30:17Z michaelld@macports.org $ +# $Id: Portfile 142646 2015-11-18 15:01:12Z michaelld@macports.org $ PortSystem 1.0 PortGroup muniversal 1.0 @@ -23,16 +23,15 @@ dist_subdir cmake subport cmake-devel {} -set branch 3.3 +set branch 3.4 if {${subport} eq ${name}} { # release - version ${branch}.2 - revision 1 - checksums rmd160 c7d3b8895e2e143b7e1019477764370535917dca \ - sha256 e75a178d6ebf182b048ebfe6e0657c49f0dc109779170bad7ffcb17463f2fc22 + version ${branch}.0 + checksums rmd160 95d3d0cd86e17c249459975eb9b293a5075ae87a \ + sha256 a5b82bf6ace6c481cdb911fd5d372a302740cbefd387e05297cb37f7468d1cea long_description ${base_long_description} \ The ${subport} release port is updated roughly every few months. @@ -41,13 +40,6 @@ if {${subport} eq ${name}} { master_sites http://www.cmake.org/files/v${branch}/ - patchfiles-append patch-Modules-noArchCheck.release.diff - - # temporary patch to find Boost 1.59; - # remove when updating to next release - - patchfiles-append patch-Modules-FindBoost.cmake.diff - livecheck.type regex livecheck.regex ${name}-(\[0-9.\]+)${extract.suffix} livecheck.url [lindex $master_sites 0] @@ -55,12 +47,12 @@ if {${subport} eq ${name}} { } else { # devel - version 20151102 + version 20151116 set dist_branch 3.4 - set dist_date 20151102 - set dist_hash g7b24b - checksums rmd160 f0aa044cc36f29eb5f962e4fc36660c9d29e7011 \ - sha256 42a24505a5927d5d37bbc79fb05d2fc4355d261b0502282639761144a45cb197 + set dist_date 20151116 + set dist_hash g89134 + checksums rmd160 6140db936ca93e0718d58694cdf8651c783cb907 \ + sha256 60cccf1952cc3faf9e7e3312ac9b7239b06cb22f0a4e24bef89b3fc901ae5474 master_sites http://www.cmake.org/files/dev/ distname ${name}-${dist_branch}.${dist_date}-${dist_hash} @@ -69,8 +61,6 @@ if {${subport} eq ${name}} { long_description ${base_long_description} \ The ${subport} port is updated roughly every week. - patchfiles-append patch-Modules-noArchCheck.devel.diff - livecheck.type regex livecheck.regex (${name}-\[0-9a-g.-\]+)${extract.suffix} livecheck.version ${distname} @@ -82,7 +72,8 @@ depends_lib-append port:curl \ port:expat \ port:zlib \ port:bzip2 \ - port:libarchive + port:libarchive \ + port:ncurses # CMake 3.2 changed dependency requirements to include jsoncpp. # jsoncpp 1.0+ requires CMake for building. catch 22. So, have CMake @@ -92,7 +83,8 @@ patchfiles-append patch-CMakeFindFrameworks.cmake.diff \ patch-Modules-FindFreetype.cmake.diff \ patch-Modules-FindQt4.cmake.diff \ patch-Modules-Platform-Darwin.cmake.diff \ - patch-Modules-Platform-Darwin-Initialize.cmake.diff + patch-Modules-Platform-Darwin-Initialize.cmake.diff \ + patch-Modules-noArchCheck.diff configure.env-append \ CMAKE_PREFIX_PATH=${prefix} \ diff --git a/tools/MacOSX/ports/devel/cmake/Portfile.patch b/tools/MacOSX/ports/devel/cmake/Portfile.patch index 729b5557a6..8a9b8be3b4 100644 --- a/tools/MacOSX/ports/devel/cmake/Portfile.patch +++ b/tools/MacOSX/ports/devel/cmake/Portfile.patch @@ -1,7 +1,7 @@ ---- Portfile.orig 2015-11-04 14:03:18.000000000 +0100 -+++ Portfile 2015-11-04 14:03:31.000000000 +0100 +--- Portfile.orig 2015-12-01 09:11:44.000000000 +0100 ++++ Portfile 2015-12-01 09:11:50.000000000 +0100 @@ -2,7 +2,7 @@ - # $Id: Portfile 142106 2015-11-03 18:30:17Z michaelld@macports.org $ + # $Id: Portfile 142646 2015-11-18 15:01:12Z michaelld@macports.org $ PortSystem 1.0 -PortGroup muniversal 1.0 diff --git a/tools/MacOSX/ports/devel/cmake/files/patch-Modules-FindBoost.cmake.diff b/tools/MacOSX/ports/devel/cmake/files/patch-Modules-FindBoost.cmake.diff deleted file mode 100644 index dc3347df41..0000000000 --- a/tools/MacOSX/ports/devel/cmake/files/patch-Modules-FindBoost.cmake.diff +++ /dev/null @@ -1,11 +0,0 @@ ---- Modules/FindBoost.cmake.orig 2015-10-04 16:06:25.000000000 +0200 -+++ Modules/FindBoost.cmake 2015-10-04 16:06:56.000000000 +0200 -@@ -512,7 +512,7 @@ - # The user has not requested an exact version. Among known - # versions, find those that are acceptable to the user request. - set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} -- "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54" -+ "1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54" - "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" - "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" - "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42" diff --git a/tools/MacOSX/ports/devel/cmake/files/patch-Modules-Platform-Darwin-Initialize.cmake.diff b/tools/MacOSX/ports/devel/cmake/files/patch-Modules-Platform-Darwin-Initialize.cmake.diff index 04dee0287a..4ac21bc59f 100644 --- a/tools/MacOSX/ports/devel/cmake/files/patch-Modules-Platform-Darwin-Initialize.cmake.diff +++ b/tools/MacOSX/ports/devel/cmake/files/patch-Modules-Platform-Darwin-Initialize.cmake.diff @@ -21,5 +21,5 @@ + set(_CMAKE_OSX_SYSROOT_DEFAULT "") + endif() endif() - else() - # Assume developer files are in root (such as Xcode 4.5 command-line tools). + if(NOT CMAKE_OSX_DEPLOYMENT_TARGET AND _CURRENT_OSX_VERSION VERSION_LESS _CMAKE_OSX_DEPLOYMENT_TARGET) + set(CMAKE_OSX_DEPLOYMENT_TARGET ${_CURRENT_OSX_VERSION} CACHE STRING diff --git a/tools/MacOSX/ports/devel/cmake/files/patch-Modules-noArchCheck.devel.diff b/tools/MacOSX/ports/devel/cmake/files/patch-Modules-noArchCheck.devel.diff deleted file mode 100644 index 3d5e577386..0000000000 --- a/tools/MacOSX/ports/devel/cmake/files/patch-Modules-noArchCheck.devel.diff +++ /dev/null @@ -1,56 +0,0 @@ ---- Modules/BasicConfigVersion-AnyNewerVersion.cmake.in.orig -+++ Modules/BasicConfigVersion-AnyNewerVersion.cmake.in -@@ -17,15 +17,3 @@ else() - set(PACKAGE_VERSION_EXACT TRUE) - endif() - endif() -- --# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: --if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "") -- return() --endif() -- --# check that the installed version has the same 32/64bit-ness as the one which is currently searching: --if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "@CMAKE_SIZEOF_VOID_P@") -- math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8") -- set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") -- set(PACKAGE_VERSION_UNSUITABLE TRUE) --endif() ---- Modules/BasicConfigVersion-ExactVersion.cmake.in.orig -+++ Modules/BasicConfigVersion-ExactVersion.cmake.in -@@ -32,16 +32,3 @@ endif() - if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) - set(PACKAGE_VERSION_EXACT TRUE) - endif() -- -- --# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: --if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "") -- return() --endif() -- --# check that the installed version has the same 32/64bit-ness as the one which is currently searching: --if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "@CMAKE_SIZEOF_VOID_P@") -- math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8") -- set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") -- set(PACKAGE_VERSION_UNSUITABLE TRUE) --endif() ---- Modules/BasicConfigVersion-SameMajorVersion.cmake.in.orig -+++ Modules/BasicConfigVersion-SameMajorVersion.cmake.in -@@ -31,16 +31,3 @@ else() - set(PACKAGE_VERSION_EXACT TRUE) - endif() - endif() -- -- --# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: --if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "") -- return() --endif() -- --# check that the installed version has the same 32/64bit-ness as the one which is currently searching: --if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "@CMAKE_SIZEOF_VOID_P@") -- math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8") -- set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") -- set(PACKAGE_VERSION_UNSUITABLE TRUE) --endif() diff --git a/tools/MacOSX/ports/devel/cmake/files/patch-Modules-noArchCheck.release.diff b/tools/MacOSX/ports/devel/cmake/files/patch-Modules-noArchCheck.release.diff deleted file mode 100644 index b5f9a7ec60..0000000000 --- a/tools/MacOSX/ports/devel/cmake/files/patch-Modules-noArchCheck.release.diff +++ /dev/null @@ -1,56 +0,0 @@ ---- Modules/BasicConfigVersion-AnyNewerVersion.cmake.in.orig -+++ Modules/BasicConfigVersion-AnyNewerVersion.cmake.in -@@ -17,15 +17,3 @@ - set(PACKAGE_VERSION_EXACT TRUE) - endif() - endif() -- --# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: --if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "") -- return() --endif() -- --# check that the installed version has the same 32/64bit-ness as the one which is currently searching: --if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "@CMAKE_SIZEOF_VOID_P@") -- math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8") -- set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") -- set(PACKAGE_VERSION_UNSUITABLE TRUE) --endif() ---- Modules/BasicConfigVersion-ExactVersion.cmake.in.orig -+++ Modules/BasicConfigVersion-ExactVersion.cmake.in -@@ -32,16 +32,3 @@ - if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) - endif() -- -- --# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: --if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "") -- return() --endif() -- --# check that the installed version has the same 32/64bit-ness as the one which is currently searching: --if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "@CMAKE_SIZEOF_VOID_P@") -- math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8") -- set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") -- set(PACKAGE_VERSION_UNSUITABLE TRUE) --endif() ---- Modules/BasicConfigVersion-SameMajorVersion.cmake.in.orig -+++ Modules/BasicConfigVersion-SameMajorVersion.cmake.in -@@ -31,16 +31,3 @@ - set(PACKAGE_VERSION_EXACT TRUE) - endif() - endif() -- -- --# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: --if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "") -- return() --endif() -- --# check that the installed version has the same 32/64bit-ness as the one which is currently searching: --if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "@CMAKE_SIZEOF_VOID_P@") -- math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8") -- set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") -- set(PACKAGE_VERSION_UNSUITABLE TRUE) --endif() diff --git a/tools/MacOSX/ports/devel/cmake/files/patch-qt4gui.devel.diff b/tools/MacOSX/ports/devel/cmake/files/patch-qt4gui.devel.diff index 500898d229..31669dc3d0 100644 --- a/tools/MacOSX/ports/devel/cmake/files/patch-qt4gui.devel.diff +++ b/tools/MacOSX/ports/devel/cmake/files/patch-qt4gui.devel.diff @@ -1,6 +1,6 @@ --- Source/QtDialog/CMakeLists.txt.orig +++ Source/QtDialog/CMakeLists.txt -@@ -15,74 +15,6 @@ +@@ -15,77 +15,6 @@ if(POLICY CMP0020) cmake_policy(SET CMP0020 NEW) # Drop when CMake >= 2.8.11 required endif() CMake_OPTIONAL_COMPONENT(cmake-gui) @@ -67,23 +67,27 @@ - endif() - endif() - -- if(WIN32 AND TARGET Qt5::Core) +- if(TARGET Qt5::Core) - get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION) - get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH) +- if(APPLE) +- get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH) +- endif() - endif() -else() set(QT_MIN_VERSION "4.4.0") find_package(Qt4 REQUIRED) if(NOT QT4_FOUND) -@@ -100,7 +32,6 @@ - set(Qt_BIN_DIR ${_Qt_BIN_DIR}) - endif() - endif() --endif() +@@ -97,8 +26,6 @@ else() + set(CMake_QT_LIBRARIES ${QT_LIBRARIES}) + +-endif() +- set(SRCS AddCacheEntry.cxx -@@ -138,7 +69,7 @@ + AddCacheEntry.h +@@ -135,7 +62,7 @@ set(SRCS ${SRCS} ${UI_SRCS} ${MOC_SRCS} ${RC_SRCS}) if(WIN32) set(SRCS ${SRCS} CMakeSetup.rc) endif() @@ -92,23 +96,20 @@ set(SRCS ${SRCS} CMakeSetup.icns) set(MACOSX_BUNDLE_ICON_FILE CMakeSetup.icns) set_source_files_properties(CMakeSetup.icns PROPERTIES -@@ -155,13 +86,13 @@ +@@ -152,10 +79,10 @@ endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) --add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS}) -+add_executable(cmake-gui WIN32 ${SRCS}) +-add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE}) ++add_executable(cmake-gui WIN32 ${SRCS} ${MANIFEST_FILE}) target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES}) - if(Qt_BIN_DIR) - set_property(TARGET cmake-gui PROPERTY Qt_BIN_DIR ${Qt_BIN_DIR}) - endif() -if(APPLE) +if(APPLEBUNDLE) file(STRINGS "${CMake_SOURCE_DIR}/Copyright.txt" copyright_line LIMIT_COUNT 1 REGEX "^Copyright 2000-20[0-9][0-9] Kitware") -@@ -206,18 +137,18 @@ +@@ -200,18 +127,18 @@ if(UNIX AND NOT APPLE) ${COMPONENT}) endif() @@ -130,9 +131,9 @@ set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/MacOS/CMake") endif() install(CODE " ---- CMakeLists.txt.orig 2015-08-03 13:51:16.000000000 -0400 -+++ CMakeLists.txt 2015-08-03 13:51:26.000000000 -0400 -@@ -566,12 +566,6 @@ +--- CMakeLists.txt.orig ++++ CMakeLists.txt +@@ -565,12 +565,6 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) set(CMAKE_BUNDLE_VERSION "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") set(CMAKE_BUNDLE_LOCATION "${CMAKE_INSTALL_PREFIX}") diff --git a/tools/MacOSX/ports/devel/cmake/files/patch-qt4gui.release.diff b/tools/MacOSX/ports/devel/cmake/files/patch-qt4gui.release.diff index 577d16b67c..75a51711d7 100644 --- a/tools/MacOSX/ports/devel/cmake/files/patch-qt4gui.release.diff +++ b/tools/MacOSX/ports/devel/cmake/files/patch-qt4gui.release.diff @@ -1,9 +1,9 @@ --- Source/QtDialog/CMakeLists.txt.orig +++ Source/QtDialog/CMakeLists.txt -@@ -14,58 +14,6 @@ - if(POLICY CMP0020) +@@ -15,77 +15,6 @@ if(POLICY CMP0020) cmake_policy(SET CMP0020 NEW) # Drop when CMake >= 2.8.11 required endif() + CMake_OPTIONAL_COMPONENT(cmake-gui) -find_package(Qt5Widgets QUIET) -if (Qt5Widgets_FOUND) - include_directories(${Qt5Widgets_INCLUDE_DIRS}) @@ -25,49 +25,69 @@ - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") - -- # We need to install Cocoa platform plugin and add qt.conf for Qt5 on Mac. +- # We need to install platform plugin and add qt.conf for Qt5 on Mac and Windows. - # FIXME: This should be part of Qt5 CMake scripts, but unfortunatelly -- # Qt5 Mac support is missing there. -- if(APPLE) +- # Qt5 support is missing there. +- if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) - macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var) - get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION) - if(EXISTS "${_qt_plugin_path}") - get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME) - get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH) - get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME) -- set(_qt_plugin_dest "PlugIns/${_qt_plugin_type}") +- if(APPLE) +- set(_qt_plugin_dir "PlugIns") +- elseif(WIN32) +- set(_qt_plugin_dir "plugins") +- endif() +- set(_qt_plugin_dest "${_qt_plugin_dir}/${_qt_plugin_type}") - install(FILES "${_qt_plugin_path}" -- DESTINATION "${_qt_plugin_dest}") +- DESTINATION "${_qt_plugin_dest}" +- ${COMPONENT}) - set(${_qt_plugins_var} - "${${_qt_plugins_var}};\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}") - else() - message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found") - endif() - endmacro() -- install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS) -- file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" -- "[Paths]\nPlugins = PlugIns\n") -- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" -- DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources") +- if(APPLE) +- install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS) +- file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" +- "[Paths]\nPlugins = ${_qt_plugin_dir}\n") +- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" +- DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources" +- ${COMPONENT}) +- elseif(WIN32) +- install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS) +- file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" +- "[Paths]\nPlugins = ../${_qt_plugin_dir}\n") +- install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" +- DESTINATION bin +- ${COMPONENT}) +- endif() - endif() - -- if(WIN32 AND TARGET Qt5::Core) +- if(TARGET Qt5::Core) - get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION) - get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH) +- if(APPLE) +- get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH) +- endif() - endif() -else() set(QT_MIN_VERSION "4.4.0") find_package(Qt4 REQUIRED) if(NOT QT4_FOUND) -@@ -83,7 +31,6 @@ - set(Qt_BIN_DIR ${_Qt_BIN_DIR}) - endif() - endif() --endif() +@@ -97,8 +26,6 @@ else() + + set(CMake_QT_LIBRARIES ${QT_LIBRARIES}) +-endif() +- set(SRCS AddCacheEntry.cxx -@@ -121,7 +68,7 @@ + AddCacheEntry.h +@@ -135,7 +62,7 @@ set(SRCS ${SRCS} ${UI_SRCS} ${MOC_SRCS} ${RC_SRCS}) if(WIN32) set(SRCS ${SRCS} CMakeSetup.rc) endif() @@ -76,34 +96,33 @@ set(SRCS ${SRCS} CMakeSetup.icns) set(MACOSX_BUNDLE_ICON_FILE CMakeSetup.icns) set_source_files_properties(CMakeSetup.icns PROPERTIES -@@ -137,13 +84,13 @@ +@@ -152,10 +79,10 @@ endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) --add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS}) -+add_executable(cmake-gui WIN32 ${SRCS}) +-add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE}) ++add_executable(cmake-gui WIN32 ${SRCS} ${MANIFEST_FILE}) target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES}) - if(Qt_BIN_DIR) - set_property(TARGET cmake-gui PROPERTY Qt_BIN_DIR ${Qt_BIN_DIR}) - endif() -if(APPLE) +if(APPLEBUNDLE) file(STRINGS "${CMake_SOURCE_DIR}/Copyright.txt" copyright_line LIMIT_COUNT 1 REGEX "^Copyright 2000-20[0-9][0-9] Kitware") -@@ -181,16 +128,16 @@ - install(FILES cmakecache.xml DESTINATION share/mime/packages ) +@@ -200,18 +127,18 @@ if(UNIX AND NOT APPLE) + ${COMPONENT}) endif() -if(APPLE) +if(APPLEBUNDLE) - install(CODE "execute_process(COMMAND ln -s \"../MacOS/CMake\" cmake-gui - WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)") + install(CODE " + execute_process(COMMAND ln -s \"../MacOS/CMake\" cmake-gui + WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin) + " ${COMPONENT}) endif() --if(APPLE OR WIN32) -+if(APPLEBUNDLE OR WIN32) +-if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) ++if(CMake_INSTALL_DEPENDENCIES AND (APPLEBUNDLE OR WIN32)) # install rules for including 3rd party libs such as Qt # if a system Qt is used (e.g. installed in /usr/lib/), it will not be included in the installation set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/cmake-gui${CMAKE_EXECUTABLE_SUFFIX}") @@ -114,7 +133,7 @@ install(CODE " --- CMakeLists.txt.orig +++ CMakeLists.txt -@@ -550,12 +550,6 @@ +@@ -563,12 +563,6 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) set(CMAKE_BUNDLE_VERSION "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") set(CMAKE_BUNDLE_LOCATION "${CMAKE_INSTALL_PREFIX}") diff --git a/tools/MacOSX/ports/devel/cmake/files/patch-qt5gui.devel.diff b/tools/MacOSX/ports/devel/cmake/files/patch-qt5gui.devel.diff index 2889d56a9e..8a7b1695aa 100644 --- a/tools/MacOSX/ports/devel/cmake/files/patch-qt5gui.devel.diff +++ b/tools/MacOSX/ports/devel/cmake/files/patch-qt5gui.devel.diff @@ -5,16 +5,16 @@ CMake_OPTIONAL_COMPONENT(cmake-gui) find_package(Qt5Widgets QUIET) -if (Qt5Widgets_FOUND) -+if (NOT Qt5Widgets_FOUND) ++if(NOT Qt5Widgets_FOUND) + message(FATAL_ERROR "Qt5 required but not found") +endif() + include_directories(${Qt5Widgets_INCLUDE_DIRS}) add_definitions(${Qt5Widgets_DEFINITONS}) macro(qt4_wrap_ui) -@@ -82,25 +85,6 @@ - get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION) - get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH) +@@ -85,19 +88,6 @@ + get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH) + endif() endif() -else() - set(QT_MIN_VERSION "4.4.0") @@ -28,17 +28,11 @@ - - set(CMake_QT_LIBRARIES ${QT_LIBRARIES}) - -- if(WIN32 AND EXISTS "${QT_QMAKE_EXECUTABLE}") -- get_filename_component(_Qt_BIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH) -- if(EXISTS "${_Qt_BIN_DIR}/QtCore4.dll") -- set(Qt_BIN_DIR ${_Qt_BIN_DIR}) -- endif() -- endif() -endif() set(SRCS AddCacheEntry.cxx -@@ -138,7 +122,7 @@ +@@ -135,7 +125,7 @@ if(WIN32) set(SRCS ${SRCS} CMakeSetup.rc) endif() @@ -47,23 +41,28 @@ set(SRCS ${SRCS} CMakeSetup.icns) set(MACOSX_BUNDLE_ICON_FILE CMakeSetup.icns) set_source_files_properties(CMakeSetup.icns PROPERTIES -@@ -155,13 +139,13 @@ +@@ -152,10 +142,10 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) --add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS}) -+add_executable(cmake-gui WIN32 ${SRCS}) +-add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE}) ++add_executable(cmake-gui WIN32 ${SRCS} ${MANIFEST_FILE}) target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES}) - if(Qt_BIN_DIR) - set_property(TARGET cmake-gui PROPERTY Qt_BIN_DIR ${Qt_BIN_DIR}) - endif() -if(APPLE) +if(APPLEBUNDLE) file(STRINGS "${CMake_SOURCE_DIR}/Copyright.txt" copyright_line LIMIT_COUNT 1 REGEX "^Copyright 2000-20[0-9][0-9] Kitware") -@@ -213,11 +197,11 @@ +@@ -200,18 +190,18 @@ + ${COMPONENT}) + endif() + +-if(APPLE) ++if(APPLEBUNDLE) + install(CODE " + execute_process(COMMAND ln -s \"../MacOS/CMake\" cmake-gui + WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin) " ${COMPONENT}) endif() @@ -79,7 +78,7 @@ install(CODE " --- CMakeLists.txt.orig +++ CMakeLists.txt -@@ -566,12 +566,6 @@ +@@ -565,12 +565,6 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) set(CMAKE_BUNDLE_VERSION "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") set(CMAKE_BUNDLE_LOCATION "${CMAKE_INSTALL_PREFIX}") diff --git a/tools/MacOSX/ports/devel/cmake/files/patch-qt5gui.release.diff b/tools/MacOSX/ports/devel/cmake/files/patch-qt5gui.release.diff index 98dc53b7af..266abc4b65 100644 --- a/tools/MacOSX/ports/devel/cmake/files/patch-qt5gui.release.diff +++ b/tools/MacOSX/ports/devel/cmake/files/patch-qt5gui.release.diff @@ -1,20 +1,20 @@ --- Source/QtDialog/CMakeLists.txt.orig +++ Source/QtDialog/CMakeLists.txt -@@ -15,7 +15,10 @@ - cmake_policy(SET CMP0020 NEW) # Drop when CMake >= 2.8.11 required +@@ -16,7 +16,10 @@ endif() + CMake_OPTIONAL_COMPONENT(cmake-gui) find_package(Qt5Widgets QUIET) -if (Qt5Widgets_FOUND) -+if (NOT Qt5Widgets_FOUND) ++if(NOT Qt5Widgets_FOUND) + message(FATAL_ERROR "Qt5 required but not found") +endif() + include_directories(${Qt5Widgets_INCLUDE_DIRS}) add_definitions(${Qt5Widgets_DEFINITONS}) macro(qt4_wrap_ui) -@@ -65,25 +68,6 @@ - get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION) - get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH) +@@ -85,19 +88,6 @@ + get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH) + endif() endif() -else() - set(QT_MIN_VERSION "4.4.0") @@ -28,17 +28,11 @@ - - set(CMake_QT_LIBRARIES ${QT_LIBRARIES}) - -- if(WIN32 AND EXISTS "${QT_QMAKE_EXECUTABLE}") -- get_filename_component(_Qt_BIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH) -- if(EXISTS "${_Qt_BIN_DIR}/QtCore4.dll") -- set(Qt_BIN_DIR ${_Qt_BIN_DIR}) -- endif() -- endif() -endif() set(SRCS AddCacheEntry.cxx -@@ -121,7 +105,7 @@ +@@ -135,7 +125,7 @@ if(WIN32) set(SRCS ${SRCS} CMakeSetup.rc) endif() @@ -47,34 +41,33 @@ set(SRCS ${SRCS} CMakeSetup.icns) set(MACOSX_BUNDLE_ICON_FILE CMakeSetup.icns) set_source_files_properties(CMakeSetup.icns PROPERTIES -@@ -137,13 +121,13 @@ +@@ -152,10 +142,10 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) --add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS}) -+add_executable(cmake-gui WIN32 ${SRCS}) +-add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE}) ++add_executable(cmake-gui WIN32 ${SRCS} ${MANIFEST_FILE}) target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES}) - if(Qt_BIN_DIR) - set_property(TARGET cmake-gui PROPERTY Qt_BIN_DIR ${Qt_BIN_DIR}) - endif() -if(APPLE) +if(APPLEBUNDLE) file(STRINGS "${CMake_SOURCE_DIR}/Copyright.txt" copyright_line LIMIT_COUNT 1 REGEX "^Copyright 2000-20[0-9][0-9] Kitware") -@@ -181,16 +165,16 @@ - install(FILES cmakecache.xml DESTINATION share/mime/packages ) +@@ -200,18 +190,18 @@ + ${COMPONENT}) endif() -if(APPLE) +if(APPLEBUNDLE) - install(CODE "execute_process(COMMAND ln -s \"../MacOS/CMake\" cmake-gui - WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)") + install(CODE " + execute_process(COMMAND ln -s \"../MacOS/CMake\" cmake-gui + WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin) + " ${COMPONENT}) endif() --if(APPLE OR WIN32) -+if(APPLEBUNDLE OR WIN32) +-if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) ++if(CMake_INSTALL_DEPENDENCIES AND (APPLEBUNDLE OR WIN32)) # install rules for including 3rd party libs such as Qt # if a system Qt is used (e.g. installed in /usr/lib/), it will not be included in the installation set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/cmake-gui${CMAKE_EXECUTABLE_SUFFIX}") @@ -85,7 +78,7 @@ install(CODE " --- CMakeLists.txt.orig +++ CMakeLists.txt -@@ -550,12 +550,6 @@ +@@ -563,12 +563,6 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) set(CMAKE_BUNDLE_VERSION "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") set(CMAKE_BUNDLE_LOCATION "${CMAKE_INSTALL_PREFIX}") diff --git a/tools/MacOSX/ports/devel/gnutls/Portfile b/tools/MacOSX/ports/devel/gnutls/Portfile index 019b64b05e..cb17a04431 100644 --- a/tools/MacOSX/ports/devel/gnutls/Portfile +++ b/tools/MacOSX/ports/devel/gnutls/Portfile @@ -1,11 +1,11 @@ # -*- Mode: Tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:et:sw=4:ts=4:sts=4 -# $Id: Portfile 140314 2015-09-17 08:26:18Z ryandesign@macports.org $ +# $Id: Portfile 142857 2015-11-25 03:15:21Z jmr@macports.org $ PortSystem 1.0 PortGroup muniversal 1.0 name gnutls -version 3.3.18 +version 3.3.19 set branch [join [lrange [split ${version} .] 0 1] .] categories devel security # yes, some of the libs are GPL only @@ -22,10 +22,11 @@ long_description \ and is available under the GNU Lesser General Public License (LGPL). master_sites ftp://ftp.gnutls.org/gcrypt/gnutls/v${branch}/ \ - http://archive.hmug.org/src/gnutls/ + http://archive.hmug.org/src/gnutls/ \ + http://mirrors.dotsrc.org/gcrypt/gnutls/v${branch}/ -checksums rmd160 76ccb9fb302284ac1ad4966bf76a8c6d9249c2ab \ - sha256 7a87e7f486d1ada10007356917a412cde6c6114dac018e3569e3aa09e9f29395 +checksums rmd160 14026faf26c94163ad88f7cf3fbe988ad9ad6d21 \ + sha256 888d8779b48f21959b33d4d9ad0b546e5ec3dea20abf0d9bb03869d56b1f44cf use_xz yes @@ -55,7 +56,8 @@ configure.args --disable-guile \ --enable-local-libopts \ --with-p11-kit \ --with-system-priority-file="${prefix}/etc/gnutls/default-priorities" \ - --with-default-trust-store-file="${prefix}/share/curl/curl-ca-bundle.crt" + --with-default-trust-store-file="${prefix}/share/curl/curl-ca-bundle.crt" \ + ac_cv_prog_AWK=/usr/bin/awk variant dane description {Build libdane using unbound libraries} { depends_lib-append port:unbound diff --git a/tools/MacOSX/ports/devel/gnutls/Portfile.orig b/tools/MacOSX/ports/devel/gnutls/Portfile.orig index bc963057e8..621e82497c 100644 --- a/tools/MacOSX/ports/devel/gnutls/Portfile.orig +++ b/tools/MacOSX/ports/devel/gnutls/Portfile.orig @@ -1,11 +1,11 @@ # -*- Mode: Tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:et:sw=4:ts=4:sts=4 -# $Id: Portfile 140314 2015-09-17 08:26:18Z ryandesign@macports.org $ +# $Id: Portfile 142857 2015-11-25 03:15:21Z jmr@macports.org $ PortSystem 1.0 PortGroup muniversal 1.0 name gnutls -version 3.3.18 +version 3.3.19 set branch [join [lrange [split ${version} .] 0 1] .] categories devel security # yes, some of the libs are GPL only @@ -22,10 +22,11 @@ long_description \ and is available under the GNU Lesser General Public License (LGPL). master_sites ftp://ftp.gnutls.org/gcrypt/gnutls/v${branch}/ \ - http://archive.hmug.org/src/gnutls/ + http://archive.hmug.org/src/gnutls/ \ + http://mirrors.dotsrc.org/gcrypt/gnutls/v${branch}/ -checksums rmd160 76ccb9fb302284ac1ad4966bf76a8c6d9249c2ab \ - sha256 7a87e7f486d1ada10007356917a412cde6c6114dac018e3569e3aa09e9f29395 +checksums rmd160 14026faf26c94163ad88f7cf3fbe988ad9ad6d21 \ + sha256 888d8779b48f21959b33d4d9ad0b546e5ec3dea20abf0d9bb03869d56b1f44cf use_xz yes @@ -55,7 +56,8 @@ configure.args --disable-guile \ --enable-local-libopts \ --with-p11-kit \ --with-system-priority-file="${prefix}/etc/gnutls/default-priorities" \ - --with-default-trust-store-file="${prefix}/share/curl/curl-ca-bundle.crt" + --with-default-trust-store-file="${prefix}/share/curl/curl-ca-bundle.crt" \ + ac_cv_prog_AWK=/usr/bin/awk variant dane description {Build libdane using unbound libraries} { depends_lib-append port:unbound diff --git a/tools/MacOSX/ports/devel/gnutls/Portfile.patch b/tools/MacOSX/ports/devel/gnutls/Portfile.patch index 6ff18eb4b3..3c7e2d9321 100644 --- a/tools/MacOSX/ports/devel/gnutls/Portfile.patch +++ b/tools/MacOSX/ports/devel/gnutls/Portfile.patch @@ -1,6 +1,6 @@ ---- Portfile.orig 2015-06-11 01:25:22.000000000 -0700 -+++ Portfile 2015-06-11 01:25:32.000000000 -0700 -@@ -82,13 +82,17 @@ +--- Portfile.orig 2015-12-01 09:13:40.000000000 +0100 ++++ Portfile 2015-12-01 09:13:46.000000000 +0100 +@@ -84,13 +84,17 @@ if {[variant_isset universal]} { set merger_host(x86_64) x86_64-apple-${os.platform}${os.major} set merger_host(i386) i686-apple-${os.platform}${os.major} diff --git a/tools/MacOSX/ports/graphics/ImageMagick/Portfile b/tools/MacOSX/ports/graphics/ImageMagick/Portfile index 1ed4f47f0b..cbba23fe87 100644 --- a/tools/MacOSX/ports/graphics/ImageMagick/Portfile +++ b/tools/MacOSX/ports/graphics/ImageMagick/Portfile @@ -148,8 +148,9 @@ variant natron conflicts x11 requires pango rsvg q32 hdri universal description configure.args-replace --with-tiff --without-tiff depends_lib-delete port:webp configure.args-replace --with-webp --without-webp - depends_lib-delete port:zlib - configure.args-replace --with-zlib --without-zlib + # zlib is required by PNG + #depends_lib-delete port:zlib + #configure.args-replace --with-zlib --without-zlib depends_lib-delete port:bzip2 configure.args-replace --with-bzlib --without-bzlib configure.args-replace --enable-shared --disable-shared diff --git a/tools/MacOSX/ports/graphics/openimageio/Portfile b/tools/MacOSX/ports/graphics/openimageio/Portfile index 8536aea8f4..9cf6b92afe 100644 --- a/tools/MacOSX/ports/graphics/openimageio/Portfile +++ b/tools/MacOSX/ports/graphics/openimageio/Portfile @@ -13,7 +13,7 @@ PortGroup qt4 1.0 epoch 1 fetch.type git -github.setup OpenImageIO oiio 1.5.20 tags/Release- +github.setup OpenImageIO oiio 1.5.21 tags/Release- #github.version ${version}-dist #github.tarball_from downloads diff --git a/tools/MacOSX/ports/multimedia/ffmpeg/Portfile b/tools/MacOSX/ports/multimedia/ffmpeg/Portfile index 6ae6e0fa73..e502f936f6 100644 --- a/tools/MacOSX/ports/multimedia/ffmpeg/Portfile +++ b/tools/MacOSX/ports/multimedia/ffmpeg/Portfile @@ -1,5 +1,5 @@ # -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 -# $Id: Portfile 141538 2015-10-20 12:25:00Z devans@macports.org $ +# $Id: Portfile 142659 2015-11-19 00:26:51Z devans@macports.org $ PortSystem 1.0 PortGroup xcodeversion 1.0 @@ -10,7 +10,8 @@ PortGroup active_variants 1.1 name ffmpeg conflicts ffmpeg-devel epoch 1 -version 2.8.1 +version 2.8.2 +revision 1 license LGPL-2.1+ categories multimedia maintainers devans jeremyhu openmaintainer @@ -52,8 +53,8 @@ master_sites http://www.ffmpeg.org/releases/ use_bzip2 yes -checksums rmd160 d679b110758fcab804ad6eaa45dc6451c614da7b \ - sha256 e2ed5ab28dee1af94336739173eb0019afc21a54e38a96f4e3208e94a07866e2 +checksums rmd160 cee6a076bead7cefb9e0c562e95465855c2c002c \ + sha256 830ec647f7ad774fc0caf17ba47774bf5dee7a89cbd65894f364a87ba3ad21b2 depends_build port:pkgconfig \ port:gmake \ @@ -81,6 +82,7 @@ depends_lib port:lame \ port:fribidi \ path:lib/libspeex.dylib:speex \ port:libsdl \ + port:soxr \ port:bzip2 \ port:xz \ port:zlib @@ -117,6 +119,7 @@ configure.args --enable-swscale \ --enable-libopenjpeg \ --enable-libmodplug \ --enable-libvpx \ + --enable-libsoxr \ --enable-libspeex \ --enable-libass \ --enable-libbluray \ diff --git a/tools/MacOSX/ports/multimedia/ffmpeg/Portfile.orig b/tools/MacOSX/ports/multimedia/ffmpeg/Portfile.orig index 1d5fe80701..9ea3f6d06d 100644 --- a/tools/MacOSX/ports/multimedia/ffmpeg/Portfile.orig +++ b/tools/MacOSX/ports/multimedia/ffmpeg/Portfile.orig @@ -1,5 +1,5 @@ # -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 -# $Id: Portfile 141538 2015-10-20 12:25:00Z devans@macports.org $ +# $Id: Portfile 142659 2015-11-19 00:26:51Z devans@macports.org $ PortSystem 1.0 PortGroup xcodeversion 1.0 @@ -10,7 +10,8 @@ PortGroup active_variants 1.1 name ffmpeg conflicts ffmpeg-devel epoch 1 -version 2.8.1 +version 2.8.2 +revision 1 license LGPL-2.1+ categories multimedia maintainers devans jeremyhu openmaintainer @@ -52,8 +53,8 @@ master_sites http://www.ffmpeg.org/releases/ use_bzip2 yes -checksums rmd160 d679b110758fcab804ad6eaa45dc6451c614da7b \ - sha256 e2ed5ab28dee1af94336739173eb0019afc21a54e38a96f4e3208e94a07866e2 +checksums rmd160 cee6a076bead7cefb9e0c562e95465855c2c002c \ + sha256 830ec647f7ad774fc0caf17ba47774bf5dee7a89cbd65894f364a87ba3ad21b2 depends_build port:pkgconfig \ port:gmake \ @@ -81,6 +82,7 @@ depends_lib port:lame \ port:fribidi \ path:lib/libspeex.dylib:speex \ port:libsdl \ + port:soxr \ port:bzip2 \ port:xz \ port:zlib @@ -116,6 +118,7 @@ configure.args --enable-swscale \ --enable-libopenjpeg \ --enable-libmodplug \ --enable-libvpx \ + --enable-libsoxr \ --enable-libspeex \ --enable-libass \ --enable-libbluray \ diff --git a/tools/MacOSX/ports/multimedia/ffmpeg/Portfile.patch b/tools/MacOSX/ports/multimedia/ffmpeg/Portfile.patch index 997a4f46e6..bec810abd0 100644 --- a/tools/MacOSX/ports/multimedia/ffmpeg/Portfile.patch +++ b/tools/MacOSX/ports/multimedia/ffmpeg/Portfile.patch @@ -1,6 +1,6 @@ ---- Portfile.orig 2015-10-27 15:27:14.000000000 +0100 -+++ Portfile 2015-10-27 15:27:20.000000000 +0100 -@@ -88,6 +88,7 @@ +--- Portfile.orig 2015-12-01 09:14:08.000000000 +0100 ++++ Portfile 2015-12-01 09:14:15.000000000 +0100 +@@ -90,6 +90,7 @@ build.cmd ${prefix}/bin/gmake build.env-append V=1 @@ -8,7 +8,7 @@ # # enable auto configure of asm optimizations # requires Xcode 3.1 or better on Leopard -@@ -130,10 +131,12 @@ +@@ -133,10 +134,12 @@ --disable-indev=jack \ --disable-outdev=xv \ --disable-vda \ @@ -22,7 +22,7 @@ # disable asm on Tiger # libblueray doesn't build on Tiger so disable for now (#39442) -@@ -168,8 +171,12 @@ +@@ -171,8 +174,12 @@ } # kCVPixelFormatType_OneComponent8 used in avfoundation indev is only available on 10.8+ @@ -37,7 +37,7 @@ } } -@@ -179,6 +186,17 @@ +@@ -182,6 +189,17 @@ # configure isn't autoconf and they do use a dep cache # @@ -55,7 +55,7 @@ post-destroot { file mkdir ${destroot}${prefix}/share/doc/ffmpeg file copy ${worksrcpath}/doc/APIchanges ${destroot}${prefix}/share/doc/ffmpeg -@@ -203,6 +221,15 @@ +@@ -206,6 +224,15 @@ configure.universal_args-delete --disable-dependency-tracking if {[variant_isset universal]} { @@ -71,7 +71,7 @@ foreach arch ${configure.universal_archs} { set merger_host($arch) "" lappend merger_configure_args($arch) --arch=${arch} -@@ -228,11 +255,55 @@ +@@ -231,11 +258,55 @@ # depends_lib-append port:xorg-libxcb \ port:xorg-libXext \ @@ -127,7 +127,7 @@ } default_variants +x11 -@@ -295,6 +366,12 @@ +@@ -298,6 +369,12 @@ port:samba3 license GPL-3+ diff --git a/tools/travis/install_dependencies.sh b/tools/travis/install_dependencies.sh index 82447da5e8..c4f4691446 100755 --- a/tools/travis/install_dependencies.sh +++ b/tools/travis/install_dependencies.sh @@ -48,7 +48,7 @@ if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then # ubuntu-toolchain-r/test contains recent versions of gcc if [ "$CC" = "$TEST_CC" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; sudo apt-get update; sudo apt-get install gcc-${GCC_VERSION} g++-${GCC_VERSION}; sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VERSION} 90; sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_VERSION} 90; fi - if [ "$CC" = "$TEST_CC" ]; then sudo pip install cpp-coveralls --use-mirrors; fi + if [ "$CC" = "$TEST_CC" ]; then sudo pip install cpp-coveralls; fi ## Python 3.4 ##sudo add-apt-repository --yes ppa:fkrull/deadsnakes # python3.x # we get libyaml-cpp-dev from kubuntu backports (for OpenColorIO)