Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 40 additions & 3 deletions App/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
# ***** END LICENSE BLOCK *****

set(Natron_SOURCES NatronApp_main.cpp)
if(WINDOWS)
list(APPEND Natron_SOURCES ../Natron.rc)
endif()
add_executable(Natron ${Natron_SOURCES})
if(WIN32)
target_sources(Natron PRIVATE ../Natron.rc)
endif()
if(APPLE)
set_target_properties(Natron PROPERTIES
MACOSX_BUNDLE TRUE
Expand Down Expand Up @@ -59,3 +59,40 @@ install(FILES ../Gui/Resources/Images/natronIcon256_linux.png
DESTINATION "${CMAKE_INSTALL_DATADIR}/pixmaps")
install(FILES ../Gui/Resources/Images/natronProjectIcon_linux.png
DESTINATION "${CMAKE_INSTALL_DATADIR}/pixmaps")

IF(WIN32 AND DEPLOYQT_FOUND)
SET(CONFIG_FILE ${CMAKE_CURRENT_BINARY_DIR}/install_deps_${CMAKE_BUILD_TYPE}.cmake)

# Find and install needed DLLs
file(GENERATE OUTPUT
"${CONFIG_FILE}" CONTENT
[[
EXECUTE_PROCESS(COMMAND del ${INSTALL_BINPATH}/*.dll)
SET(TARGET_APP $<TARGET_FILE:Natron>)
FILE(GET_RUNTIME_DEPENDENCIES
RESOLVED_DEPENDENCIES_VAR deps_resolved
UNRESOLVED_DEPENDENCIES_VAR deps_unresolved
EXECUTABLES ${TARGET_APP}
DIRECTORIES ${CMAKELIBPATH}
PRE_EXCLUDE_REGEXES "api-ms-*" "ext-ms-*"
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
)
MESSAGE(STATUS "Resolving runtime dependencies for ${TARGET_APP}")
FOREACH(dep ${deps_resolved})
FILE(INSTALL ${dep} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
MESSAGE(STATUS "Installing ${dep}")
ENDFOREACH()
FOREACH(dep ${deps_unresolved})
MESSAGE(WARNING "Runtime dependency ${dep} could not be resolved.")
ENDFOREACH()
EXECUTE_PROCESS(COMMAND ${DEPLOYQT_EXE} --no-angle --compiler-runtime ${INSTALL_BINPATH}/Natron.exe)
]])

INSTALL(CODE "SET(INSTALL_BINPATH \"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}\")")
INSTALL(CODE "SET(DEPLOYQT_EXE \"${DEPLOYQT_EXE}\")")
INSTALL(CODE "SET(CMAKELIBPATH \"${CMAKE_SYSTEM_LIBRARY_PATH};${CMAKE_MINGW_SYSTEM_LIBRARY_PATH};${MINGWPATH}\")")
INSTALL(SCRIPT ${CONFIG_FILE})
INSTALL(DIRECTORY ${Python3_LIBRARY_DIRS}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}
DESTINATION lib
PATTERN "*.pyc" EXCLUDE)
ENDIF()
16 changes: 15 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ if(WIN32)
endif()
find_package(Python3 COMPONENTS Interpreter Development)

if(WIN32)
# Search qtdeploy executable
find_program(DEPLOYQT_EXE windeployqt.exe)
if(NOT ${DEPLOYQT_EXE} STREQUAL "")
set(DEPLOYQT_FOUND 1)
message(STATUS "windeployqt.exe found : ${DEPLOYQT_EXE}")
else()
set(DEPLOYQT_FOUND 0)
message(STATUS "windeployqt.exe not found, will not deploy Qt dependencies")
endif()
endif()

if(IS_DEBUG_BUILD AND WIN32)
# Explicitly setting SHIBOKEN_PYTHON_LIBRARIES variable to avoid PYTHON_DEBUG_LIBRARY-NOTFOUND
# link errors on Windows debug builds.
Expand All @@ -84,7 +96,7 @@ if(NATRON_QT6)
set(SHIBOKEN_LIB Shiboken6::libshiboken)
set(PYSIDE_LIB PySide6::pyside6)
else()
find_package(Qt5 5.15 CONFIG REQUIRED COMPONENTS ${QT_COMPONENTS})
find_package(Qt5 5.15 CONFIG REQUIRED COMPONENTS ${QT_COMPONENTS} NO_SYSTEM_ENVIRONMENT_PATH)
find_package(Shiboken2 5.15 CONFIG REQUIRED COMPONENTS libshiboken2 shiboken2)

find_package(PySide2 5.15 CONFIG REQUIRED COMPONENTS pyside2)
Expand All @@ -101,6 +113,8 @@ else()
set(PYSIDE_LIB PySide2::pyside2)
endif()

message(STATUS ">>> qt dirs ${Qt5Gui_INCLUDE_DIRS}")

if(IS_DEBUG_BUILD AND WIN32)
# Remove NDEBUG from Shiboken INTERFACE_COMPILE_DEFINITIONS so it is not inherited in debug builds.
get_property(SHIBOKEN_DEFS TARGET ${SHIBOKEN_LIB} PROPERTY INTERFACE_COMPILE_DEFINITIONS)
Expand Down
8 changes: 8 additions & 0 deletions Engine/AppInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,18 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON
{
}

virtual void loadProjectGui(bool /*isAutosave*/, boost::archive::binary_iarchive & /*archive*/) const
{
}

virtual void saveProjectGui(boost::archive::xml_oarchive & /*archive*/)
{
}

virtual void saveProjectGui(boost::archive::binary_oarchive & /*archive*/)
{
}

virtual void setupViewersForViews(const std::vector<std::string>& /*viewNames*/)
{
}
Expand Down
8 changes: 6 additions & 2 deletions Engine/AppManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,9 @@ AppManager::loadFromArgs(const CLArgs& cl)
std::cout << "argv[" << i << "] = " << StrUtils::utf16_to_utf8( std::wstring(_imp->commandLineArgsWide[i]) ) << std::endl;
}
#endif
// This should fix GL widgets when undocked
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);

// This needs to be done BEFORE creating qApp because
// on Linux, X11 will create a context that would corrupt
Expand All @@ -322,6 +325,7 @@ AppManager::loadFromArgs(const CLArgs& cl)
_imp->renderingContextPool.reset( new GPUContextPool() );
initializeOpenGLFunctionsOnce(true);


// QCoreApplication will hold a reference to that appManagerArgc integer until it dies.
// Thus ensure that the QCoreApplication is destroyed when returning this function.
initializeQApp(_imp->nArgs, &_imp->commandLineArgsUtf8.front()); // calls QCoreApplication::QCoreApplication(), which calls setlocale()
Expand Down Expand Up @@ -3182,7 +3186,7 @@ void
AppManager::registerUNCPath(const QString& path,
const QChar& driveLetter)
{
assert( QThread::currentThread() == qApp->thread() );
//assert( QThread::currentThread() == qApp->thread() );
_imp->uncPathMapping[driveLetter] = path;
}

Expand Down Expand Up @@ -4189,7 +4193,7 @@ NATRON_PYTHON_NAMESPACE::getFunctionArguments(const std::string& pyFunc,
#endif
std::stringstream ss;
ss << "import inspect\n";
ss << "args_spec = inspect.getargspec(" << pyFunc << ")\n";
ss << "args_spec = inspect.getfullargspec(" << pyFunc << ")\n";
std::string script = ss.str();
std::string output;
bool ok = NATRON_PYTHON_NAMESPACE::interpretPythonScript(script, error, &output);
Expand Down
2 changes: 2 additions & 0 deletions Engine/EngineFwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ namespace boost {
namespace archive {
class xml_iarchive;
class xml_oarchive;
class binary_iarchive;
class binary_oarchive;
}
namespace serialization {
class access;
Expand Down
155 changes: 113 additions & 42 deletions Engine/Project.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,6 @@ Project::loadProjectInternal(const QString & path,
}

bool ret = false;
FStreamsSupport::ifstream ifile;
FStreamsSupport::open( &ifile, filePath.toStdString() );
if (!ifile) {
throw std::runtime_error( tr("Failed to open %1").arg(filePath).toStdString() );
}

if ( (NATRON_VERSION_MAJOR == 1) && (NATRON_VERSION_MINOR == 0) && (NATRON_VERSION_REVISION == 0) ) {
///Try to determine if the project was made during Natron v1.0.0 - RC2 or RC3 to detect a bug we introduced at that time
Expand All @@ -315,21 +310,28 @@ Project::loadProjectInternal(const QString & path,
}

LoadProjectSplashScreen_RAII __raii_splashscreen__(getApp(), name);
bool xml_loaded = false;

try {
bool bgProject;
boost::archive::xml_iarchive iArchive(ifile);
{
FlagSetter __raii_loadingProjectInternal__(true, &_imp->isLoadingProjectInternal, &_imp->isLoadingProjectMutex);
// XML loading tests first, then binary loading
FStreamsSupport::ifstream ifile;
FStreamsSupport::open( &ifile, filePath.toStdString());
if (ifile) {
bool bgProject;
boost::archive::xml_iarchive iArchive(ifile);
{
FlagSetter __raii_loadingProjectInternal__(true, &_imp->isLoadingProjectInternal, &_imp->isLoadingProjectMutex);

iArchive >> boost::serialization::make_nvp("Background_project", bgProject);
ProjectSerialization projectSerializationObj( getApp() );
iArchive >> boost::serialization::make_nvp("Project", projectSerializationObj);
ret = load(projectSerializationObj, name, path, mustSave);
} // __raii_loadingProjectInternal__

iArchive >> boost::serialization::make_nvp("Background_project", bgProject);
ProjectSerialization projectSerializationObj( getApp() );
iArchive >> boost::serialization::make_nvp("Project", projectSerializationObj);
ret = load(projectSerializationObj, name, path, mustSave);
} // __raii_loadingProjectInternal__

if (!bgProject) {
getApp()->loadProjectGui(isAutoSave, iArchive);
if (!bgProject) {
getApp()->loadProjectGui(isAutoSave, iArchive);
}
xml_loaded = true;
}
} catch (const std::exception &e) {
const ProjectBeingLoadedInfo& pInfo = getApp()->getProjectBeingLoadedInfo();
Expand All @@ -339,7 +341,6 @@ Project::loadProjectInternal(const QString & path,
QString message = tr("This project was saved with a more recent version (%1.%2.%3) of %4. Projects are not forward compatible and may only be opened in a version of %4 equal or more recent than the version that saved it.").arg(pInfo.vMajor).arg(pInfo.vMinor).arg(pInfo.vRev).arg(QString::fromUtf8(NATRON_APPLICATION_NAME));
throw std::runtime_error(message.toStdString());
}
throw std::runtime_error( tr("Unrecognized or damaged project file:").toStdString() + ' ' + e.what());
} catch (...) {
const ProjectBeingLoadedInfo& pInfo = getApp()->getProjectBeingLoadedInfo();
if (pInfo.vMajor > NATRON_VERSION_MAJOR ||
Expand All @@ -348,7 +349,48 @@ Project::loadProjectInternal(const QString & path,
QString message = tr("This project was saved with a more recent version (%1.%2.%3) of %4. Projects are not forward compatible and may only be opened in a version of %4 equal or more recent than the version that saved it.").arg(pInfo.vMajor).arg(pInfo.vMinor).arg(pInfo.vRev).arg(QString::fromUtf8(NATRON_APPLICATION_NAME));
throw std::runtime_error(message.toStdString());
}
throw std::runtime_error( tr("Unrecognized or damaged project file").toStdString() );
}

if (!xml_loaded){
try {
FStreamsSupport::ifstream ifile;
FStreamsSupport::open( &ifile, filePath.toStdString(), std::ios::in | std::ios::binary );
if (!ifile) {
throw std::runtime_error( tr("Failed to open %1").arg(filePath).toStdString() );
}
bool bgProject;
boost::archive::binary_iarchive iArchive(ifile);
{
FlagSetter __raii_loadingProjectInternal__(true, &_imp->isLoadingProjectInternal, &_imp->isLoadingProjectMutex);

iArchive >> boost::serialization::make_nvp("Background_project", bgProject);
ProjectSerialization projectSerializationObj( getApp() );
iArchive >> boost::serialization::make_nvp("Project", projectSerializationObj);
ret = load(projectSerializationObj, name, path, mustSave);
} // __raii_loadingProjectInternal__

if (!bgProject) {
getApp()->loadProjectGui(isAutoSave, iArchive);
}
} catch (const std::exception &e) {
const ProjectBeingLoadedInfo& pInfo = getApp()->getProjectBeingLoadedInfo();
if (pInfo.vMajor > NATRON_VERSION_MAJOR ||
(pInfo.vMajor == NATRON_VERSION_MAJOR && pInfo.vMinor > NATRON_VERSION_MINOR) ||
(pInfo.vMajor == NATRON_VERSION_MAJOR && pInfo.vMinor == NATRON_VERSION_MINOR && pInfo.vRev > NATRON_VERSION_REVISION)) {
QString message = tr("This project was saved with a more recent version (%1.%2.%3) of %4. Projects are not forward compatible and may only be opened in a version of %4 equal or more recent than the version that saved it.").arg(pInfo.vMajor).arg(pInfo.vMinor).arg(pInfo.vRev).arg(QString::fromUtf8(NATRON_APPLICATION_NAME));
throw std::runtime_error(message.toStdString());
}
throw std::runtime_error( tr("Unrecognized or damaged project file:").toStdString() + ' ' + e.what());
} catch (...) {
const ProjectBeingLoadedInfo& pInfo = getApp()->getProjectBeingLoadedInfo();
if (pInfo.vMajor > NATRON_VERSION_MAJOR ||
(pInfo.vMajor == NATRON_VERSION_MAJOR && pInfo.vMinor > NATRON_VERSION_MINOR) ||
(pInfo.vMajor == NATRON_VERSION_MAJOR && pInfo.vMinor == NATRON_VERSION_MINOR && pInfo.vRev > NATRON_VERSION_REVISION)) {
QString message = tr("This project was saved with a more recent version (%1.%2.%3) of %4. Projects are not forward compatible and may only be opened in a version of %4 equal or more recent than the version that saved it.").arg(pInfo.vMajor).arg(pInfo.vMinor).arg(pInfo.vRev).arg(QString::fromUtf8(NATRON_APPLICATION_NAME));
throw std::runtime_error(message.toStdString());
}
throw std::runtime_error( tr("Unrecognized or damaged project file").toStdString() );
}
}

Format f;
Expand Down Expand Up @@ -599,12 +641,6 @@ Project::saveProjectInternal(const QString & path,
tmpFilename.append( QString::number( time.toMSecsSinceEpoch() ) );

{
FStreamsSupport::ofstream ofile;
FStreamsSupport::open( &ofile, tmpFilename.toStdString() );
if (!ofile) {
throw std::runtime_error( tr("Failed to open file ").toStdString() + tmpFilename.toStdString() );
}

///Fix file paths before saving.
QString oldProjectPath = QString::fromUtf8( _imp->getProjectPath().c_str() );

Expand All @@ -615,27 +651,62 @@ Project::saveProjectInternal(const QString & path,
_imp->natronVersion->setValue( generateUserFriendlyNatronVersionName() );
}

try {
boost::archive::xml_oarchive oArchive(ofile);
bool bgProject = getApp()->isBackground();
oArchive << boost::serialization::make_nvp("Background_project", bgProject);
ProjectSerialization projectSerializationObj( getApp() );
save(&projectSerializationObj);
oArchive << boost::serialization::make_nvp("Project", projectSerializationObj);
if (!bgProject) {
AppInstancePtr app = getApp();
if (app) {
app->saveProjectGui(oArchive);
if (!appPTR->getCurrentSettings()->saveAsBinary()){
try {
FStreamsSupport::ofstream ofile;
FStreamsSupport::open( &ofile, tmpFilename.toStdString(), std::ios::out);
if (!ofile) {
throw std::runtime_error( tr("Failed to open file ").toStdString() + tmpFilename.toStdString() );
}
boost::archive::xml_oarchive oArchive(ofile);
bool bgProject = getApp()->isBackground();
oArchive << boost::serialization::make_nvp("Background_project", bgProject);
ProjectSerialization projectSerializationObj( getApp() );
save(&projectSerializationObj);
oArchive << boost::serialization::make_nvp("Project", projectSerializationObj);
if (!bgProject) {
AppInstancePtr app = getApp();
if (app) {
app->saveProjectGui(oArchive);
}
}
} catch (...) {
if (!autoSave && updateProjectProperties) {
///Reset the old project path in case of failure.
_imp->autoSetProjectDirectory(oldProjectPath);
}
throw;
}
} catch (...) {
if (!autoSave && updateProjectProperties) {
///Reset the old project path in case of failure.
_imp->autoSetProjectDirectory(oldProjectPath);
}
else
{
try {
FStreamsSupport::ofstream ofile;
FStreamsSupport::open( &ofile, tmpFilename.toStdString(), std::ios::out | std::ios::binary);
if (!ofile) {
throw std::runtime_error( tr("Failed to open file ").toStdString() + tmpFilename.toStdString() );
}
boost::archive::binary_oarchive oArchive(ofile);
bool bgProject = getApp()->isBackground();
oArchive << boost::serialization::make_nvp("Background_project", bgProject);
ProjectSerialization projectSerializationObj( getApp() );
save(&projectSerializationObj);
oArchive << boost::serialization::make_nvp("Project", projectSerializationObj);
if (!bgProject) {
AppInstancePtr app = getApp();
if (app) {
app->saveProjectGui(oArchive);
}
}
} catch (...) {
if (!autoSave && updateProjectProperties) {
///Reset the old project path in case of failure.
_imp->autoSetProjectDirectory(oldProjectPath);
}
throw;
}
throw;
}
} // ofile
}

if (!autoSave) {
// rotate backups
Expand Down
13 changes: 13 additions & 0 deletions Engine/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ Settings::initializeKnobsGeneral()
"last saved), *.~2~ (third last saved).") );
_generalTab->addKnob(_saveVersions);

_saveAsBinary = AppManager::createKnob<KnobBool>( this, tr("Save projects as binary") );
_saveAsBinary->setName("saveAsBinary");
_saveAsBinary->setHintToolTip( tr("When checked, %1 will save projects in a binary format which is faster to load and save. "
"When unchecked, projects will be saved in a human-readable text format. "
"Note that the text format is not guaranteed to be stable across versions of %1.").arg( QString::fromUtf8(NATRON_APPLICATION_NAME) ) );

_hostName = AppManager::createKnob<KnobChoice>( this, tr("Appear to plug-ins as") );
_hostName->setName("pluginHostName");
_hostName->setHintToolTip( tr("%1 will appear with the name of the selected application to the OpenFX plug-ins. "
Expand Down Expand Up @@ -1469,6 +1475,7 @@ Settings::setDefaultValues()
_autoSaveUnSavedProjects->setDefaultValue(true);
_autoSaveDelay->setDefaultValue(5, 0);
_saveVersions->setDefaultValue(1);
_saveAsBinary->setDefaultValue(false);
_hostName->setDefaultValue(0);
_customHostName->setDefaultValue(NATRON_ORGANIZATION_DOMAIN_TOPLEVEL "." NATRON_ORGANIZATION_DOMAIN_SUB "." NATRON_APPLICATION_NAME);

Expand Down Expand Up @@ -2912,6 +2919,12 @@ Settings::saveVersions() const
return _saveVersions->getValue();
}

bool
Settings::saveAsBinary() const
{
return _saveAsBinary->getValue();
}


bool
Settings::isSnapToNodeEnabled() const
Expand Down
Loading