From 6e024e4fa04c1948a034006982349f48f41a01ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 20 Oct 2024 21:49:53 +0200 Subject: [PATCH 01/23] macOS Redux https://github.com/orgs/friction2d/discussions/267 --- CMakeLists.txt | 2 +- src/app/CMakeLists.txt | 6 ++- src/app/GUI/mainwindow.cpp | 15 ++++++- src/app/memorychecker.cpp | 67 ++++++++++++++++---------------- src/cmake/friction-common.cmake | 10 +++-- src/core/appsupport.cpp | 7 +++- src/engine/CMakeLists.txt | 12 ++++++ src/engine/skia | 2 +- src/ui/widgets/canvastoolbar.cpp | 3 ++ src/ui/widgets/colortoolbar.cpp | 3 ++ 10 files changed, 83 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ea056830a..148efc8a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,7 @@ endif() if(${BUILD_ENGINE}) add_subdirectory(src/engine) endif() -if(UNIX) +if(UNIX AND NOT APPLE) option(BUILD_TESTING "Don't build gperftools tests" OFF) add_subdirectory(src/gperftools) endif() diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 1c8ae10c4..d3a774c25 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -37,6 +37,10 @@ if(${LINUX_DEPLOY}) endif() option(USE_SKIA_SYSTEM_LIBS "Use skia (third-party) system libraries on Linux" ON) +if(APPLE) + set(USE_SKIA_SYSTEM_LIBS OFF) +endif() + if(${USE_SKIA_SYSTEM_LIBS} AND UNIX) pkg_check_modules(EXPAT REQUIRED expat) pkg_check_modules(FREETYPE REQUIRED freetype2) @@ -54,7 +58,7 @@ endif() if(APPLE) set(ICON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/icons/${PROJECT_NAME}.icns) - set(MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME}) + set(MACOSX_BUNDLE_BUNDLE_NAME "Friction") set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}) set(MACOSX_BUNDLE_LONG_VERSION_STRING ${PROJECT_VERSION}) set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") diff --git a/src/app/GUI/mainwindow.cpp b/src/app/GUI/mainwindow.cpp index efc377713..2ddc3f724 100644 --- a/src/app/GUI/mainwindow.cpp +++ b/src/app/GUI/mainwindow.cpp @@ -1045,13 +1045,19 @@ void MainWindow::setupMenuBar() }); help->addSeparator(); + + QString cmdDefKey = "Ctrl+Space"; +#ifdef Q_OS_MAC + cmdDefKey = "Alt+Space"; +#endif + help->addAction(QIcon::fromTheme("cmd"), tr("Command Palette"), this, [this]() { CommandPalette dialog(mDocument, this); dialog.exec(); }, QKeySequence(AppSupport::getSettings("shortcuts", "cmdPalette", - "Ctrl+Space").toString())); + cmdDefKey).toString())); help->addSeparator(); help->addAction(QIcon::fromTheme("renderlayers"), @@ -1075,6 +1081,7 @@ void MainWindow::setupMenuBar() setMenuBar(mMenuBar); +#ifndef Q_OS_MAC const auto frictionButton = new QPushButton(this); frictionButton->setFlat(true); frictionButton->setIcon(QIcon::fromTheme(AppSupport::getAppID())); @@ -1086,6 +1093,7 @@ void MainWindow::setupMenuBar() mMenuBar->setCornerWidget(frictionButton, Qt::TopRightCorner); +#endif } BoundingBox *MainWindow::getCurrentBox() @@ -1325,8 +1333,11 @@ void MainWindow::setupToolBar() mToolbar->setFocusPolicy(Qt::NoFocus); mToolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); mToolbar->setMovable(false); +#ifdef Q_OS_MAC + mToolbar->setStyleSheet(QString("font-size: %1pt;").arg(font().pointSize())); +#endif eSizesUI::widget.add(mToolbar, [this](const int size) { - mToolbar->setIconSize(QSize(size, size)); + mToolbar->setIconSize({size, size}); }); addToolBar(Qt::TopToolBarArea, mToolbar); } diff --git a/src/app/memorychecker.cpp b/src/app/memorychecker.cpp index fb8bfb8bd..4514fcd9d 100644 --- a/src/app/memorychecker.cpp +++ b/src/app/memorychecker.cpp @@ -29,9 +29,9 @@ #if defined(Q_OS_WIN) #include "windowsincludes.h" #elif defined(Q_OS_UNIX) - #include "gperftools/tcmalloc.h" - #include "../gperftools/include/gperftools/malloc_extension.h" #if defined(Q_OS_LINUX) + #include "gperftools/tcmalloc.h" + #include "../gperftools/include/gperftools/malloc_extension.h" #include #include #elif defined(Q_OS_MACOS) @@ -39,6 +39,9 @@ #include #include #include + #include + #include + #include #endif #endif @@ -62,12 +65,14 @@ MemoryChecker::MemoryChecker(QObject * const parent) : QObject(parent) { char MemoryChecker::sLine[256]; -void MemoryChecker::sGetFreeKB(intKB& procFreeKB, intKB& sysFreeKB) { +void MemoryChecker::sGetFreeKB(intKB& procFreeKB, intKB& sysFreeKB) +{ const auto usageCap = eSettings::sInstance->fRamMBCap; longB enveUsedB(0); qint64 freeInternal = 0; intKB freeExternal(0); + #if defined(Q_OS_WIN) const auto processID = GetCurrentProcessId(); const auto hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, @@ -86,53 +91,54 @@ void MemoryChecker::sGetFreeKB(intKB& procFreeKB, intKB& sysFreeKB) { const longB availPhysB(statex.ullAvailPhys); freeExternal = intKB(availPhysB); #elif defined(Q_OS_UNIX) - // qDebug() << ""; - size_t virtual_memory_used; - size_t physical_memory_used; - size_t bytes_in_use_by_app; + size_t physical_memory_used = 0; + size_t bytes_in_use_by_app = 0; +#if defined(Q_OS_LINUX) + size_t virtual_memory_used = 0; MallocExtension::instance()->eMemoryStats(&virtual_memory_used, &physical_memory_used, &bytes_in_use_by_app); -// qDebug() << "virtual_memory_used" << intMB(longB(virtual_memory_used)).fValue; -// qDebug() << "physical_memory_used" << intMB(longB(physical_memory_used)).fValue; -// qDebug() << "bytes_in_use_by_app" << intMB(longB(bytes_in_use_by_app)).fValue; +#elif defined(Q_OS_MACOS) + struct mach_task_basic_info info; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO, + (task_info_t)&info, &infoCount ) == KERN_SUCCESS ) { + bytes_in_use_by_app = info.resident_size; + } +#endif +#endif enveUsedB = longB(static_cast(bytes_in_use_by_app)); freeInternal = physical_memory_used - bytes_in_use_by_app; - #if defined(Q_OS_LINUX) +#if defined(Q_OS_LINUX) int found = 0; FILE * const meminfo = fopen("/proc/meminfo", "r"); - if(!meminfo) RuntimeThrow("Failed to open /proc/meminfo"); + if (!meminfo) { RuntimeThrow("Failed to open /proc/meminfo"); } while(fgets(sLine, sizeof(sLine), meminfo)) { int ramPartKB; - if(sscanf(sLine, "MemFree: %d kB", &ramPartKB) == 1) { - // qDebug() << "MemFree" << intMB(intKB(ramPartKB)).fValue; + if (sscanf(sLine, "MemFree: %d kB", &ramPartKB) == 1) { } else if(sscanf(sLine, "Cached: %d kB", &ramPartKB) == 1) { - // qDebug() << "Cached" << intMB(intKB(ramPartKB)).fValue; } else if(sscanf(sLine, "Buffers: %d kB", &ramPartKB) == 1) { - // qDebug() << "Buffers" << intMB(intKB(ramPartKB)).fValue; - } else continue; + } else { continue; } freeExternal.fValue += ramPartKB; if(++found == 3) break; } fclose(meminfo); if(found != 3) RuntimeThrow("Entries missing from /proc/meminfo"); - #elif defined(Q_OS_MACOS) +#elif defined(Q_OS_MACOS) mach_msg_type_number_t count = HOST_VM_INFO_COUNT; vm_statistics_data_t vmstat; const auto ret = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmstat, &count); - if(ret != KERN_SUCCESS) RuntimeThrow("Could not retrieve memory usage"); - // auto total = vmstat.wire_count + vmstat.active_count + vmstat.inactive_count + vmstat.free_count; + if (ret != KERN_SUCCESS) { RuntimeThrow("Could not retrieve memory usage"); } const int pageSize = 4; - freeExternal.fValue += vmstat.inactive_count * 4; - freeExternal.fValue += vmstat.free_count * 4; - #endif + freeExternal.fValue += vmstat.inactive_count * pageSize; + freeExternal.fValue += vmstat.free_count * pageSize; #endif const intKB enveUsedKB(enveUsedB); - if(usageCap.fValue > 0) { + if (usageCap.fValue > 0) { procFreeKB = intKB(usageCap) - enveUsedKB; } else { procFreeKB = HardwareInfo::sRamKB() - enveUsedKB; @@ -140,17 +146,12 @@ void MemoryChecker::sGetFreeKB(intKB& procFreeKB, intKB& sysFreeKB) { sysFreeKB = intKB(longB(freeInternal)) + freeExternal; -// qDebug() << "free" << intMB(sysFreeKB).fValue; -// qDebug() << "usage" << 100 - 100*sysFreeKB.fValue/HardwareInfo::sRamKB().fValue; +#if defined(Q_OS_LINUX) const qint64 releaseBytes = 500L*1024L*1024L; - if(freeInternal > releaseBytes) { -#if defined(Q_OS_WIN) - -#elif defined(Q_OS_UNIX) - MallocExtension::instance()->ReleaseToSystem(releaseBytes); -// qDebug() << "released"; -#endif + if (freeInternal > releaseBytes) { + MallocExtension::instance()->ReleaseToSystem(releaseBytes); } +#endif } void MemoryChecker::checkMemory() { diff --git a/src/cmake/friction-common.cmake b/src/cmake/friction-common.cmake index 3acf0cee7..94ea047a1 100644 --- a/src/cmake/friction-common.cmake +++ b/src/cmake/friction-common.cmake @@ -37,10 +37,12 @@ if(${WIN_DEPLOY}) add_definitions(-DWIN_DEPLOY) endif() -if(UNIX AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - message(FATAL_ERROR "Only Clang is supported.") -elseif(WIN32 AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - message(FATAL_ERROR "Only MSVC is supported.") +if(NOT APPLE) + if(UNIX AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Only Clang is supported.") + elseif(WIN32 AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + message(FATAL_ERROR "Only MSVC is supported.") + endif() endif() if(UNIX) diff --git a/src/core/appsupport.cpp b/src/core/appsupport.cpp index 95abbf9d2..ccd8b8939 100644 --- a/src/core/appsupport.cpp +++ b/src/core/appsupport.cpp @@ -1001,8 +1001,9 @@ void AppSupport::checkFFmpeg(const bool &isRenderer) void AppSupport::initEnv(const bool &isRenderer) { +#if defined(Q_OS_WIN) + Q_UNUSED(isRenderer) // windows theme integration -#ifdef Q_OS_WIN #if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) // Set window title bar color based on dark/light theme // https://www.qt.io/blog/dark-mode-on-windows-11-with-qt-6.5 @@ -1011,12 +1012,14 @@ void AppSupport::initEnv(const bool &isRenderer) QSettings::NativeFormat); if (registry.value("AppsUseLightTheme", 0).toInt() == 0) { qputenv("QT_QPA_PLATFORM", "windows:darkmode=1"); } #endif -#else +#elif defined(Q_OS_LINUX) if (isRenderer) { // Force Mesa if Renderer qputenv("LIBGL_ALWAYS_SOFTWARE", "1"); } // Force XCB on Linux until we support Wayland qputenv("QT_QPA_PLATFORM", isRenderer ? "offscreen" : "xcb"); +#else + Q_UNUSED(isRenderer) #endif } diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 5228e6a09..a2f6fb69b 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -31,6 +31,10 @@ option(SYNC_SKIA_DEPS "Sync third-party depends" ON) set(SKIA_SRC "${CMAKE_CURRENT_SOURCE_DIR}/skia") set(SKIA_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/skia") +if(APPLE) + set(USE_SKIA_SYSTEM_LIBS OFF) +endif() + if(${USE_SKIA_SYSTEM_LIBS} AND UNIX) set(SKIA_ENABLE_EXTERNAL "true") else() @@ -71,6 +75,11 @@ else() else() set(SKIA_ARGS "${SKIA_ARGS} extra_cflags=[\"-Wno-error\", \"-Wno-psabi\"]") endif() + if(APPLE) + set(GN_PATH ${SKIA_SRC}/bin/gn.bin) + set(SKIA_UPDATE_CMD python3 "tools/git-sync-deps") + set(SKIA_ARGS "${SKIA_ARGS} extra_cflags_cc=[\"-frtti\"]") + endif() endif() set(SKIA_ARGS "${SKIA_ARGS} is_official_build=true is_debug=false") @@ -87,6 +96,9 @@ endif() if(UNIX AND NOT APPLE) set(SKIA_ARGS "${SKIA_ARGS} skia_use_system_freetype2=${SKIA_ENABLE_EXTERNAL}") endif() +if(APPLE) + set(SKIA_ARGS "${SKIA_ARGS} skia_use_libgifcodec=false") +endif() message("-- skia args: ${SKIA_ARGS}") diff --git a/src/engine/skia b/src/engine/skia index 3d55448fe..e4dfe1480 160000 --- a/src/engine/skia +++ b/src/engine/skia @@ -1 +1 @@ -Subproject commit 3d55448feb27f949b19d4a3809e40ecf3bb5532a +Subproject commit e4dfe1480dd3388be77907bb198de9d3cb39f63b diff --git a/src/ui/widgets/canvastoolbar.cpp b/src/ui/widgets/canvastoolbar.cpp index 44e3f734c..0b2a98423 100644 --- a/src/ui/widgets/canvastoolbar.cpp +++ b/src/ui/widgets/canvastoolbar.cpp @@ -46,6 +46,9 @@ CanvasToolBar::CanvasToolBar(QWidget *parent) setWindowTitle(tr("Canvas Toolbar")); setObjectName("CanvasToolBar"); setToolButtonStyle(Qt::ToolButtonTextBesideIcon); +#ifdef Q_OS_MAC + setStyleSheet(QString("font-size: %1pt;").arg(font().pointSize())); +#endif { const auto space = new QWidget(this); diff --git a/src/ui/widgets/colortoolbar.cpp b/src/ui/widgets/colortoolbar.cpp index 534ff116f..388a5ca1e 100644 --- a/src/ui/widgets/colortoolbar.cpp +++ b/src/ui/widgets/colortoolbar.cpp @@ -43,6 +43,9 @@ ColorToolBar::ColorToolBar(Document &document, setWindowTitle(tr("Color Toolbar")); setObjectName("ColorToolBar"); setToolButtonStyle(Qt::ToolButtonTextBesideIcon); +#ifdef Q_OS_MAC + setStyleSheet(QString("font-size: %1pt;").arg(font().pointSize())); +#endif setEnabled(false); setMovable(AppSupport::getSettings("ui", "ColorToolBarMovable", From 5f50e525777d196519b64378d02720701feba9bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 20 Oct 2024 22:07:46 +0200 Subject: [PATCH 02/23] Update memorychecker.cpp --- src/app/memorychecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/memorychecker.cpp b/src/app/memorychecker.cpp index 4514fcd9d..20963b52e 100644 --- a/src/app/memorychecker.cpp +++ b/src/app/memorychecker.cpp @@ -105,7 +105,6 @@ void MemoryChecker::sGetFreeKB(intKB& procFreeKB, intKB& sysFreeKB) (task_info_t)&info, &infoCount ) == KERN_SUCCESS ) { bytes_in_use_by_app = info.resident_size; } -#endif #endif enveUsedB = longB(static_cast(bytes_in_use_by_app)); @@ -135,6 +134,7 @@ void MemoryChecker::sGetFreeKB(intKB& procFreeKB, intKB& sysFreeKB) const int pageSize = 4; freeExternal.fValue += vmstat.inactive_count * pageSize; freeExternal.fValue += vmstat.free_count * pageSize; +#endif #endif const intKB enveUsedKB(enveUsedB); From 58cd0497d2731a0808c2c92bd883ded269f76f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 20 Oct 2024 22:08:43 +0200 Subject: [PATCH 03/23] Update BUILD.md --- BUILD.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/BUILD.md b/BUILD.md index 7fcf29b02..bfbef819b 100644 --- a/BUILD.md +++ b/BUILD.md @@ -41,15 +41,30 @@ Generic instructions for building Friction on supported systems. * `cmake` must be available in `PATH` * `python3` must be available in `PATH` * [LLVM](https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.7/LLVM-15.0.7-win64.exe) installed to default location -* Qt 5.15.14 libraries and headers in `friction\sdk` +* Qt 5.15 libraries and headers in `friction\sdk` * See [configure_qt5.bat](src/scripts/configure_qt5.bat) and [build_qt5.bat](src/scripts/build_qt5.bat) -* QScintilla 2.14.1 libraries and headers in `friction\sdk` +* QScintilla libraries and headers in `friction\sdk` * See [build_qscintilla.bat](src/scripts/build_qscintilla.bat) -* FFmpeg 4.2.9 libraries and headers in `friction\sdk` +* FFmpeg 4.2 libraries and headers in `friction\sdk` * See [build_mxe_ffmpeg.sh](src/scripts/build_mxe_ffmpeg.sh) and [mxe](https://github.com/friction2d/mxe) Binary SDK available [here](https://github.com/friction2d/friction-sdk/releases). +## Requirements on macOS + +* macOS Monterey 12.7 x86-64 +* Xcode 14.2 *(Apple clang 14)* + +Install required packages from macports: + +``` +sudo port install qt5-qtbase qt5-qttools qt5-qtmultimedia qt5-qtdeclarative qscintilla-qt5 ffmpeg pkgconfig ninja +``` +### Notes + +* FFmpeg in macports is not supported *(render issues)*, a custom Portfile or build will be made available. +* `python` and `python3` must be available in `PATH` and point to a Python 3 install. + ## Get Source ``` From 8d4e3747fa1c0840c846a7095b0c3413a8ecb3b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 20 Oct 2024 22:27:20 +0200 Subject: [PATCH 04/23] Update skia --- src/engine/skia | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/skia b/src/engine/skia index e4dfe1480..994b99419 160000 --- a/src/engine/skia +++ b/src/engine/skia @@ -1 +1 @@ -Subproject commit e4dfe1480dd3388be77907bb198de9d3cb39f63b +Subproject commit 994b99419594173a2049943ca34b9bfd6758110c From b5622509cd49c4b59e7be0ffdb7612825256f91d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Mon, 21 Oct 2024 17:34:18 +0200 Subject: [PATCH 05/23] Refactored Color Pick Mode --- src/app/GUI/mainwindow.cpp | 28 ++++++- src/app/GUI/mainwindow.h | 4 + src/app/GUI/toolbox.cpp | 7 +- src/core/Private/document.cpp | 4 + src/core/Private/document.h | 1 + src/core/actions.cpp | 3 +- src/core/canvas.cpp | 4 + src/core/canvas.h | 4 + src/core/canvasmouseevents.cpp | 35 ++++++--- src/core/canvasmouseinteractions.cpp | 41 ++++------ src/ui/CMakeLists.txt | 2 - src/ui/widgets/colorpickingwidget.cpp | 103 ------------------------- src/ui/widgets/colorpickingwidget.h | 67 ---------------- src/ui/widgets/colorsettingswidget.cpp | 23 ++++-- 14 files changed, 104 insertions(+), 222 deletions(-) delete mode 100644 src/ui/widgets/colorpickingwidget.cpp delete mode 100644 src/ui/widgets/colorpickingwidget.h diff --git a/src/app/GUI/mainwindow.cpp b/src/app/GUI/mainwindow.cpp index efc377713..d88f04201 100644 --- a/src/app/GUI/mainwindow.cpp +++ b/src/app/GUI/mainwindow.cpp @@ -154,6 +154,7 @@ MainWindow::MainWindow(Document& document, , mViewFillStrokeAct(nullptr) , mRenderWindow(nullptr) , mRenderWindowAct(nullptr) + , mColorPickLabel(nullptr) { Q_ASSERT(!sInstance); sInstance = this; @@ -188,6 +189,8 @@ MainWindow::MainWindow(Document& document, this, &MainWindow::openApplyExpressionDialog); connect(&mDocument, &Document::newVideo, this, &MainWindow::handleNewVideoClip); + connect(&mDocument, &Document::currentPixelColor, + this, &MainWindow::handleCurrentPixelColor); setWindowIcon(QIcon::fromTheme(AppSupport::getAppName())); @@ -327,6 +330,10 @@ MainWindow::MainWindow(Document& document, statusBar()->addPermanentWidget(mCanvasToolBar); + mColorPickLabel = new QLabel(this); + mColorPickLabel->setVisible(false); + statusBar()->addWidget(mColorPickLabel); + // final layout mUI = new UILayout(this); std::vector docks; @@ -1349,6 +1356,11 @@ void MainWindow::updateCanvasModeButtonsChecked() mToolBoxDraw->setEnabled(drawMode); mToolBoxDraw->setVisible(drawMode); mLocalPivotAct->setEnabled(pointMode || boxMode); + + if (mColorPickLabel) { + mColorPickLabel->clear(); + mColorPickLabel->setVisible(mode == CanvasMode::pickFillStroke); + } } void MainWindow::setResolutionValue(const qreal value) @@ -2090,4 +2102,18 @@ void MainWindow::handleNewVideoClip(const VideoBox::VideoSpecs &specs) // open dialog if ask AdjustSceneDialog dialog(scene, specs, this); dialog.exec(); - } +} + +void MainWindow::handleCurrentPixelColor(const QColor &color) +{ + if (!color.isValid()) { + mColorPickLabel->clear(); + return; + } + mColorPickLabel->setText(QString("  " + "      " + "RGB %1, %2, %3").arg(QString::number(color.redF()), + QString::number(color.greenF()), + QString::number(color.blueF()), + color.name())); +} diff --git a/src/app/GUI/mainwindow.h b/src/app/GUI/mainwindow.h index 91ee1ad47..0f2dcef36 100644 --- a/src/app/GUI/mainwindow.h +++ b/src/app/GUI/mainwindow.h @@ -215,6 +215,8 @@ class MainWindow : public QMainWindow void handleNewVideoClip(const VideoBox::VideoSpecs &specs); + void handleCurrentPixelColor(const QColor &color); + TimelineDockWidget *mTimeline; RenderWidget *mRenderWidget; @@ -380,6 +382,8 @@ class MainWindow : public QMainWindow void initRenderPresets(const bool reinstall = false); void askInstallRenderPresets(); + QLabel *mColorPickLabel; + protected: void keyPressEvent(QKeyEvent *event); bool eventFilter(QObject *obj, QEvent *e); diff --git a/src/app/GUI/toolbox.cpp b/src/app/GUI/toolbox.cpp index 46b14712c..773107e61 100644 --- a/src/app/GUI/toolbox.cpp +++ b/src/app/GUI/toolbox.cpp @@ -248,8 +248,8 @@ void MainWindow::setupToolBoxMain() mToolBoxGroupMain->addAction(nullModeAct); // pickMode - /*QAction *pickModeAct = new QAction(QIcon::fromTheme("pick"), - tr("Pick Mode"), + QAction *pickModeAct = new QAction(QIcon::fromTheme("pick"), + tr("Color Pick Mode"), this); pickModeAct->setCheckable(true); pickModeAct->setShortcut(QKeySequence(AppSupport::getSettings("shortcuts", @@ -269,7 +269,8 @@ void MainWindow::setupToolBoxMain() pickModeAct->setChecked(true); } }); - mToolBoxGroupMain->addAction(pickModeAct);*/ + + mToolBoxGroupMain->addAction(pickModeAct); mToolBoxMain->addActions(mToolBoxGroupMain->actions()); diff --git a/src/core/Private/document.cpp b/src/core/Private/document.cpp index 30436648c..29c056064 100644 --- a/src/core/Private/document.cpp +++ b/src/core/Private/document.cpp @@ -169,6 +169,10 @@ void Document::setActiveScene(Canvas * const scene) { this, [this](QrealAnimator* const target) { emit openApplyExpressionDialog(target); }); + conn << connect(fActiveScene, &Canvas::currentHoverColor, + this, [this](const QColor &color) { + emit currentPixelColor(color); + }); emit currentBoxChanged(fActiveScene->getCurrentBox()); emit selectedPaintSettingsChanged(); } diff --git a/src/core/Private/document.h b/src/core/Private/document.h index 3419e45e7..cd1e2bb9f 100644 --- a/src/core/Private/document.h +++ b/src/core/Private/document.h @@ -214,6 +214,7 @@ class CORE_EXPORT Document : public SingleWidgetTarget { void openExpressionDialog(QrealAnimator* const target); void openApplyExpressionDialog(QrealAnimator* const target); void newVideo(const VideoBox::VideoSpecs specs); + void currentPixelColor(const QColor &color); }; #endif // DOCUMENT_H diff --git a/src/core/actions.cpp b/src/core/actions.cpp index 12be42bb0..368b0df01 100644 --- a/src/core/actions.cpp +++ b/src/core/actions.cpp @@ -828,8 +828,7 @@ void Actions::setRectangleMode() { } void Actions::setPickPaintSettingsMode() { - // mDocument.setCanvasMode(CanvasMode::pickFillStroke); - // Disabled, why would anyone use this? + mDocument.setCanvasMode(CanvasMode::pickFillStroke); } void Actions::setCircleMode() { diff --git a/src/core/canvas.cpp b/src/core/canvas.cpp index ad292a0bd..c7a8f06ee 100644 --- a/src/core/canvas.cpp +++ b/src/core/canvas.cpp @@ -770,6 +770,10 @@ void Canvas::updatePivot() void Canvas::setCanvasMode(const CanvasMode mode) { + if (mCurrentMode == CanvasMode::pickFillStroke) { + emit currentPickedColor(QColor()); + emit currentHoverColor(QColor()); + } mCurrentMode = mode; mSelecting = false; mStylusDrawing = false; diff --git a/src/core/canvas.h b/src/core/canvas.h index 9852dd9e8..9a72b7f45 100644 --- a/src/core/canvas.h +++ b/src/core/canvas.h @@ -450,6 +450,8 @@ class CORE_EXPORT Canvas : public CanvasBase void openMarkerEditor(); void openExpressionDialog(QrealAnimator* const target); void openApplyExpressionDialog(QrealAnimator* const target); + void currentPickedColor(const QColor &color); + void currentHoverColor(const QColor &color); public: void makePointCtrlsSymmetric(); @@ -734,6 +736,8 @@ class CORE_EXPORT Canvas : public CanvasBase void drawPathClear(); void drawPathFinish(const qreal invScale); + const QColor pickPixelColor(const QPoint &pos); + qreal mLastDRot = 0; int mRotHalfCycles = 0; TransformMode mTransMode = TransformMode::none; diff --git a/src/core/canvasmouseevents.cpp b/src/core/canvasmouseevents.cpp index e593981f7..1886a75da 100644 --- a/src/core/canvasmouseevents.cpp +++ b/src/core/canvasmouseevents.cpp @@ -70,13 +70,18 @@ void Canvas::mousePressEvent(const eMouseEvent &e) { } } -void Canvas::mouseMoveEvent(const eMouseEvent &e) { - if(mStylusDrawing) return; - if(isPreviewingOrRendering()) return; +void Canvas::mouseMoveEvent(const eMouseEvent &e) +{ + if (mStylusDrawing) { return; } + if (isPreviewingOrRendering()) { return; } const bool leftPressed = e.fButtons & Qt::LeftButton; - if(!leftPressed && !e.fMouseGrabbing) { + if (!leftPressed && !e.fMouseGrabbing) { + if (mCurrentMode == CanvasMode::pickFillStroke) { + emit currentHoverColor(pickPixelColor(e.fGlobalPos)); + return; + } const auto lastHoveredBox = mHoveredBox; const auto lastHoveredPoint = mHoveredPoint_d; const auto lastNSegment = mHoveredNormalSegment; @@ -153,17 +158,25 @@ void Canvas::mouseMoveEvent(const eMouseEvent &e) { e.fGrabMouse(); } -void Canvas::mouseReleaseEvent(const eMouseEvent &e) { - if(isPreviewingOrRendering()) return; - if(e.fButton == Qt::RightButton) { - if(mCurrentMode == CanvasMode::paint) { - } else if(mCurrentMode == CanvasMode::drawPath) { +void Canvas::mouseReleaseEvent(const eMouseEvent &e) +{ + if (isPreviewingOrRendering()) { return; } + if (e.fButton == Qt::RightButton) { + switch(mCurrentMode) { + case CanvasMode::paint: + break; + case CanvasMode::drawPath: drawPathClear(); - } else { + break; + case CanvasMode::pickFillStroke: + emit currentPickedColor(QColor()); + emit currentHoverColor(QColor()); + break; + default: handleRightButtonMouseRelease(e); } } - if(e.fButton != Qt::LeftButton) return; + if (e.fButton != Qt::LeftButton) { return; } schedulePivotUpdate(); /*if(mCurrentMode == CanvasMode::paint) { const auto paintMode = mDocument.fPaintMode; diff --git a/src/core/canvasmouseinteractions.cpp b/src/core/canvasmouseinteractions.cpp index 31db01357..7add50dab 100644 --- a/src/core/canvasmouseinteractions.cpp +++ b/src/core/canvasmouseinteractions.cpp @@ -51,6 +51,8 @@ #include "MovablePoints/smartnodepoint.h" #include "MovablePoints/pathpivot.h" +#include +#include #include #include #include @@ -242,7 +244,7 @@ void Canvas::handleLeftButtonMousePress(const eMouseEvent& e) { mDrawPath.lineTo(e.fPos); } } else if(mCurrentMode == CanvasMode::pickFillStroke) { - mPressedBox = getBoxAtFromAllDescendents(e.fPos); + //mPressedBox = getBoxAtFromAllDescendents(e.fPos); } else if(mCurrentMode == CanvasMode::circleCreate) { const auto newPath = enve::make_shared(); newPath->planCenterPivotPosition(); @@ -512,6 +514,17 @@ void Canvas::drawPathFinish(const qreal invScale) { drawPathClear(); } +const QColor Canvas::pickPixelColor(const QPoint &pos) +{ + QScreen *screen = QApplication::screenAt(pos); + if (!screen) { return QColor(); } + WId wid = QApplication::desktop()->winId(); + QImage img = screen->grabWindow(wid, + pos.x(), pos.y(), + 1, 1).toImage(); + return QColor(img.pixel(0, 0)); +} + void Canvas::handleLeftMouseRelease(const eMouseEvent &e) { if(e.fMouseGrabbing) e.fReleaseMouse(); if(mCurrentNormalSegment.isValid()) { @@ -541,31 +554,7 @@ void Canvas::handleLeftMouseRelease(const eMouseEvent &e) { drawPathFinish(1/e.fScale); } } else if(mCurrentMode == CanvasMode::pickFillStroke) { - if(mPressedBox && enve_cast(mPressedBox)) { - const auto srcPathBox = static_cast(mPressedBox.data()); - for(const auto& box : mSelectedBoxes) { - if(const auto pathBox = enve_cast(box)) { - if(e.ctrlMod()) { - if(e.shiftMod()) { - pathBox->duplicateStrokeSettingsFrom( - srcPathBox->getStrokeSettings()); - } else { - pathBox->duplicateFillSettingsFrom( - srcPathBox->getFillSettings()); - } - } else { - if(e.shiftMod()) { - pathBox->duplicateStrokeSettingsNotAnimatedFrom( - srcPathBox->getStrokeSettings()); - } else { - pathBox->duplicateFillSettingsNotAnimatedFrom( - srcPathBox->getFillSettings()); - } - } - } - } - } - //mCanvasWindow->setCanvasMode(MOVE_PATH); + emit currentPickedColor(pickPixelColor(e.fGlobalPos)); } mValueInput.clearAndDisableInput(); mTransMode = TransformMode::none; diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index a9d28bdc1..fb3388af7 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -75,7 +75,6 @@ set( widgets/canvassettingswidget.cpp widgets/canvastoolbar.cpp widgets/changewidthwidget.cpp - widgets/colorpickingwidget.cpp widgets/colortoolbar.cpp widgets/colortoolbutton.cpp widgets/colorlabel.cpp @@ -147,7 +146,6 @@ set( widgets/canvassettingswidget.h widgets/canvastoolbar.h widgets/changewidthwidget.h - widgets/colorpickingwidget.h widgets/colortoolbar.h widgets/colortoolbutton.h widgets/colorlabel.h diff --git a/src/ui/widgets/colorpickingwidget.cpp b/src/ui/widgets/colorpickingwidget.cpp deleted file mode 100644 index 67a00689c..000000000 --- a/src/ui/widgets/colorpickingwidget.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* -# -# Friction - https://friction.graphics -# -# Copyright (c) Ole-André Rodlie and contributors -# -# This program 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 3 of the License, or -# (at your option) any later version. -# -# This program 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 this program. If not, see . -# -# See 'README.md' for more information. -# -*/ - -// Fork of enve - Copyright (C) 2016-2020 Maurycy Liebner - -#include "colorpickingwidget.h" -#include "Private/document.h" -#include "GUI/global.h" - -#include -#include -#include -#include - -ColorPickingWidget::ColorPickingWidget(QScreen* const screen, - QWidget * const parent) - : QWidget(parent) { - mScreenshot = screen->grabWindow(0).toImage(); - - setCursor(Qt::PointingHandCursor); - - setMouseTracking(true); - - setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint); - setAttribute(Qt::WA_DeleteOnClose); - - showFullScreen(); - setFocus(); -} - -void ColorPickingWidget::mousePressEvent(QMouseEvent *e) { - if(e->button() == Qt::RightButton) { - close(); - } else if(e->button() == Qt::LeftButton) { - emit colorSelected(mCurrentColor); - Document::sInstance->actionFinished(); - close(); - } -} - -void ColorPickingWidget::paintEvent(QPaintEvent *) { - QPainter p(this); - p.drawImage(0, 0, mScreenshot); - p.fillRect(mCursorX + 2*eSizesUI::widget - 4, - mCursorY - eSizesUI::widget - 4, - eSizesUI::widget + 8, - eSizesUI::widget + 8, Qt::black); - p.fillRect(mCursorX + 2*eSizesUI::widget - 2, - mCursorY - eSizesUI::widget - 2, - eSizesUI::widget + 4, - eSizesUI::widget + 4, Qt::white); - p.fillRect(mCursorX + 2*eSizesUI::widget, - mCursorY - eSizesUI::widget, - eSizesUI::widget, eSizesUI::widget, - mCurrentColor); - p.end(); -} - -void ColorPickingWidget::keyPressEvent(QKeyEvent *e) { - if(e->isAutoRepeat()) return; - close(); -} - -void ColorPickingWidget::mouseMoveEvent(QMouseEvent *e) { - updateBox(e->pos()); -} - -void ColorPickingWidget::focusOutEvent(QFocusEvent*) { - close(); -} - -QColor ColorPickingWidget::colorFromPoint(const int x, const int y) { - const QRgb rgb = mScreenshot.pixel(x, y); - return QColor::fromRgb(rgb); -} - -void ColorPickingWidget::updateBox(const QPoint& pos) { - mCursorX = pos.x(); - mCursorY = pos.y(); - qreal pixelRatio = devicePixelRatioF(); - mCurrentColor = colorFromPoint(pos.x() * pixelRatio, pos.y() * pixelRatio); - update(); -} diff --git a/src/ui/widgets/colorpickingwidget.h b/src/ui/widgets/colorpickingwidget.h deleted file mode 100644 index 164fcc2b2..000000000 --- a/src/ui/widgets/colorpickingwidget.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -# -# Friction - https://friction.graphics -# -# Copyright (c) Ole-André Rodlie and contributors -# -# This program 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 3 of the License, or -# (at your option) any later version. -# -# This program 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 this program. If not, see . -# -# See 'README.md' for more information. -# -*/ - -// Fork of enve - Copyright (C) 2016-2020 Maurycy Liebner - -#ifndef COLORPICKINGWIDGET_H -#define COLORPICKINGWIDGET_H - -#include "ui_global.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -class UI_EXPORT ColorPickingWidget : public QWidget -{ - Q_OBJECT -public: - explicit ColorPickingWidget(QScreen* const screen, - QWidget * const parent = nullptr); - -protected: - void mousePressEvent(QMouseEvent *e); - void paintEvent(QPaintEvent *); - void keyPressEvent(QKeyEvent *e); - void mouseMoveEvent(QMouseEvent *e); - void focusOutEvent(QFocusEvent*); - -signals: - void colorSelected(QColor); - -private: - QColor colorFromPoint(const int x, const int y); - void updateBox(const QPoint &pos); - - QImage mScreenshot; - QColor mCurrentColor; - int mCursorX = 0; - int mCursorY = 0; -}; - -#endif // COLORPICKINGWIDGET_H diff --git a/src/ui/widgets/colorsettingswidget.cpp b/src/ui/widgets/colorsettingswidget.cpp index 141e43f45..5494524c9 100644 --- a/src/ui/widgets/colorsettingswidget.cpp +++ b/src/ui/widgets/colorsettingswidget.cpp @@ -24,7 +24,6 @@ // Fork of enve - Copyright (C) 2016-2020 Maurycy Liebner #include "colorsettingswidget.h" -#include "widgets/colorpickingwidget.h" #include "colorhelpers.h" #include "widgets/colorlabel.h" #include "GUI/global.h" @@ -32,6 +31,7 @@ #include "appsupport.h" #include "Private/esettings.h" #include "Private/document.h" +#include "canvas.h" #include #include @@ -283,12 +283,21 @@ void ColorSettingsWidget::moveAlphaWidgetToTab(const int tabId) { void ColorSettingsWidget::startColorPicking() { - const auto wid = new ColorPickingWidget(this->screen(), this); - connect(wid, &ColorPickingWidget::colorSelected, - [this](const QColor & color) { - emitStartFullColorChangedSignal(); - setDisplayedColor(color); - emitFinishFullColorChangedSignal(); + const auto scene = *Document::sInstance->fActiveScene; + if (!scene) { return; } + CanvasMode lastMode = Document::sInstance->fCanvasMode; + Document::sInstance->setCanvasMode(CanvasMode::pickFillStroke); + auto conn = std::make_shared(); + *conn = connect(scene, &Canvas::currentPickedColor, + this, [this, conn, lastMode](const QColor &color) { + qDebug() << "selected color" << color << color.isValid(); + if (color.isValid()) { + emitStartFullColorChangedSignal(); + setDisplayedColor(color); + emitFinishFullColorChangedSignal(); + } + disconnect(*conn); + Document::sInstance->setCanvasMode(lastMode); }); } From 178b802176c4af9c6d3946e1baa03c957f9850ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Tue, 22 Oct 2024 12:51:07 +0200 Subject: [PATCH 06/23] Update icons --- src/app/icons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/icons b/src/app/icons index 2730fe7ae..c74c8879f 160000 --- a/src/app/icons +++ b/src/app/icons @@ -1 +1 @@ -Subproject commit 2730fe7ae44ee954495b5a5ae457da6cee9a2533 +Subproject commit c74c8879fbb69fe8a124d1a83a3d377dfaa779b0 From 962452d77a560096ce91f170b610089c60c86543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Tue, 22 Oct 2024 17:31:20 +0200 Subject: [PATCH 07/23] PaintSettingsAnimator: undo on setCurrentColor When needed, usually this function is run by something else with undo support. --- src/core/Animators/paintsettingsanimator.cpp | 12 +++++++++++- src/core/Animators/paintsettingsanimator.h | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/core/Animators/paintsettingsanimator.cpp b/src/core/Animators/paintsettingsanimator.cpp index e286ae39b..bc2289518 100644 --- a/src/core/Animators/paintsettingsanimator.cpp +++ b/src/core/Animators/paintsettingsanimator.cpp @@ -386,7 +386,17 @@ void PaintSettingsAnimator::setGradient(Gradient* gradient) { setGradientVar(gradient); } -void PaintSettingsAnimator::setCurrentColor(const QColor &color) { +void PaintSettingsAnimator::setCurrentColor(const QColor &color, + const bool &history) +{ + if (history) { + UndoRedo ur; + const auto oldValue = mColor->getColor(); + const auto newValue = color; + ur.fUndo = [this, oldValue]() { setCurrentColor(oldValue); }; + ur.fRedo = [this, newValue]() { setCurrentColor(newValue); }; + prp_addUndoRedo(ur); + } mColor->setColor(color); } diff --git a/src/core/Animators/paintsettingsanimator.h b/src/core/Animators/paintsettingsanimator.h index b522188e7..e349745b7 100644 --- a/src/core/Animators/paintsettingsanimator.h +++ b/src/core/Animators/paintsettingsanimator.h @@ -66,7 +66,8 @@ class CORE_EXPORT PaintSettingsAnimator : public ComplexAnimator { PaintType getPaintType() const; Gradient *getGradient() const; void setGradient(Gradient *gradient); - void setCurrentColor(const QColor &color); + void setCurrentColor(const QColor &color, + const bool &history = false); ColorAnimator *getColorAnimator(); void setGradientPointsPos(const QPointF& pt1, const QPointF& pt2); From af65b3e70ffcec0efaadda80bfbeba645e2e67d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Tue, 22 Oct 2024 17:44:29 +0200 Subject: [PATCH 08/23] Canvas: add 'applyPixelColor' color picker refactor part deux. --- src/core/canvas.h | 2 ++ src/core/canvasmouseinteractions.cpp | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/core/canvas.h b/src/core/canvas.h index 9a72b7f45..b72965db7 100644 --- a/src/core/canvas.h +++ b/src/core/canvas.h @@ -737,6 +737,8 @@ class CORE_EXPORT Canvas : public CanvasBase void drawPathFinish(const qreal invScale); const QColor pickPixelColor(const QPoint &pos); + void applyPixelColor(const QColor &color, + const bool &fill); qreal mLastDRot = 0; int mRotHalfCycles = 0; diff --git a/src/core/canvasmouseinteractions.cpp b/src/core/canvasmouseinteractions.cpp index 7add50dab..95dcc3057 100644 --- a/src/core/canvasmouseinteractions.cpp +++ b/src/core/canvasmouseinteractions.cpp @@ -525,6 +525,27 @@ const QColor Canvas::pickPixelColor(const QPoint &pos) return QColor(img.pixel(0, 0)); } +void Canvas::applyPixelColor(const QColor &color, + const bool &fill) +{ + if (!color.isValid()) { return; } + for (const auto& box : mSelectedBoxes) { + if (fill) { + auto settings = box->getFillSettings(); + if (settings) { + settings->setCurrentColor(color, true); + box->fillStrokeSettingsChanged(); + } + } else { + auto settings = box->getStrokeSettings(); + if (settings) { + settings->setCurrentColor(color, true); + box->fillStrokeSettingsChanged(); + } + } + } +} + void Canvas::handleLeftMouseRelease(const eMouseEvent &e) { if(e.fMouseGrabbing) e.fReleaseMouse(); if(mCurrentNormalSegment.isValid()) { From 044773dbbcb4ce4c0463aaca7f7ef8d70d7d2240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Tue, 22 Oct 2024 19:13:47 +0200 Subject: [PATCH 09/23] Color picker refactor part deux Seems to work as it should, need to test for bugs. --- src/app/GUI/canvaswindow.cpp | 1 + src/app/GUI/mainwindow.cpp | 3 ++- src/app/GUI/toolbox.cpp | 3 ++- src/core/Properties/property.h | 3 ++- src/core/canvas.cpp | 3 ++- src/core/canvasmouseevents.cpp | 11 ++++++++++- src/core/canvasmouseinteractions.cpp | 8 +++++--- src/ui/widgets/colorsettingswidget.cpp | 2 +- 8 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/app/GUI/canvaswindow.cpp b/src/app/GUI/canvaswindow.cpp index 05265daa6..9cf76a96c 100644 --- a/src/app/GUI/canvaswindow.cpp +++ b/src/app/GUI/canvaswindow.cpp @@ -128,6 +128,7 @@ void CanvasWindow::setCanvasMode(const CanvasMode mode) setCursor(Qt::ArrowCursor); break; case CanvasMode::pickFillStroke: + case CanvasMode::pickFillStrokeEvent: setCursor(Qt::PointingHandCursor); break; case CanvasMode::circleCreate: diff --git a/src/app/GUI/mainwindow.cpp b/src/app/GUI/mainwindow.cpp index d88f04201..570e4b846 100644 --- a/src/app/GUI/mainwindow.cpp +++ b/src/app/GUI/mainwindow.cpp @@ -1359,7 +1359,8 @@ void MainWindow::updateCanvasModeButtonsChecked() if (mColorPickLabel) { mColorPickLabel->clear(); - mColorPickLabel->setVisible(mode == CanvasMode::pickFillStroke); + mColorPickLabel->setVisible(mode == CanvasMode::pickFillStroke || + mode == CanvasMode::pickFillStrokeEvent); } } diff --git a/src/app/GUI/toolbox.cpp b/src/app/GUI/toolbox.cpp index 773107e61..7cd6af479 100644 --- a/src/app/GUI/toolbox.cpp +++ b/src/app/GUI/toolbox.cpp @@ -265,7 +265,8 @@ void MainWindow::setupToolBoxMain() &Document::canvasModeSet, this, [this, pickModeAct]() { - if (mDocument.fCanvasMode == CanvasMode::pickFillStroke) { + if (mDocument.fCanvasMode == CanvasMode::pickFillStroke || + mDocument.fCanvasMode == CanvasMode::pickFillStrokeEvent) { pickModeAct->setChecked(true); } }); diff --git a/src/core/Properties/property.h b/src/core/Properties/property.h index 227abcc6e..af995fef5 100644 --- a/src/core/Properties/property.h +++ b/src/core/Properties/property.h @@ -56,7 +56,8 @@ enum class CanvasMode : short { textCreate, nullCreate, - pickFillStroke + pickFillStroke, + pickFillStrokeEvent }; enum class UpdateReason { diff --git a/src/core/canvas.cpp b/src/core/canvas.cpp index c7a8f06ee..e52845c5c 100644 --- a/src/core/canvas.cpp +++ b/src/core/canvas.cpp @@ -770,7 +770,8 @@ void Canvas::updatePivot() void Canvas::setCanvasMode(const CanvasMode mode) { - if (mCurrentMode == CanvasMode::pickFillStroke) { + if (mCurrentMode == CanvasMode::pickFillStroke || + mCurrentMode == CanvasMode::pickFillStrokeEvent) { emit currentPickedColor(QColor()); emit currentHoverColor(QColor()); } diff --git a/src/core/canvasmouseevents.cpp b/src/core/canvasmouseevents.cpp index 1886a75da..f3e342d02 100644 --- a/src/core/canvasmouseevents.cpp +++ b/src/core/canvasmouseevents.cpp @@ -78,7 +78,8 @@ void Canvas::mouseMoveEvent(const eMouseEvent &e) const bool leftPressed = e.fButtons & Qt::LeftButton; if (!leftPressed && !e.fMouseGrabbing) { - if (mCurrentMode == CanvasMode::pickFillStroke) { + if (mCurrentMode == CanvasMode::pickFillStroke || + mCurrentMode == CanvasMode::pickFillStrokeEvent) { emit currentHoverColor(pickPixelColor(e.fGlobalPos)); return; } @@ -169,6 +170,9 @@ void Canvas::mouseReleaseEvent(const eMouseEvent &e) drawPathClear(); break; case CanvasMode::pickFillStroke: + applyPixelColor(pickPixelColor(e.fGlobalPos), false); + break; + case CanvasMode::pickFillStrokeEvent: emit currentPickedColor(QColor()); emit currentHoverColor(QColor()); break; @@ -177,6 +181,11 @@ void Canvas::mouseReleaseEvent(const eMouseEvent &e) } } if (e.fButton != Qt::LeftButton) { return; } + if (e.fButton == Qt::LeftButton && + mCurrentMode == CanvasMode::pickFillStroke) { + applyPixelColor(pickPixelColor(e.fGlobalPos), true); + return; + } schedulePivotUpdate(); /*if(mCurrentMode == CanvasMode::paint) { const auto paintMode = mDocument.fPaintMode; diff --git a/src/core/canvasmouseinteractions.cpp b/src/core/canvasmouseinteractions.cpp index 95dcc3057..6f5b0e5e6 100644 --- a/src/core/canvasmouseinteractions.cpp +++ b/src/core/canvasmouseinteractions.cpp @@ -243,7 +243,8 @@ void Canvas::handleLeftButtonMousePress(const eMouseEvent& e) { drawPathClear(); mDrawPath.lineTo(e.fPos); } - } else if(mCurrentMode == CanvasMode::pickFillStroke) { + } else if (mCurrentMode == CanvasMode::pickFillStroke || + mCurrentMode == CanvasMode::pickFillStrokeEvent) { //mPressedBox = getBoxAtFromAllDescendents(e.fPos); } else if(mCurrentMode == CanvasMode::circleCreate) { const auto newPath = enve::make_shared(); @@ -302,7 +303,8 @@ void Canvas::cancelCurrentTransform() { } } else if(mCurrentMode == CanvasMode::pathCreate) { - } else if(mCurrentMode == CanvasMode::pickFillStroke) { + } else if (mCurrentMode == CanvasMode::pickFillStroke || + mCurrentMode == CanvasMode::pickFillStrokeEvent) { //mCanvasWindow->setCanvasMode(MOVE_PATH); } mValueInput.clearAndDisableInput(); @@ -574,7 +576,7 @@ void Canvas::handleLeftMouseRelease(const eMouseEvent &e) { } else { drawPathFinish(1/e.fScale); } - } else if(mCurrentMode == CanvasMode::pickFillStroke) { + } else if (mCurrentMode == CanvasMode::pickFillStrokeEvent) { emit currentPickedColor(pickPixelColor(e.fGlobalPos)); } mValueInput.clearAndDisableInput(); diff --git a/src/ui/widgets/colorsettingswidget.cpp b/src/ui/widgets/colorsettingswidget.cpp index 5494524c9..1c0f3bf15 100644 --- a/src/ui/widgets/colorsettingswidget.cpp +++ b/src/ui/widgets/colorsettingswidget.cpp @@ -286,7 +286,7 @@ void ColorSettingsWidget::startColorPicking() const auto scene = *Document::sInstance->fActiveScene; if (!scene) { return; } CanvasMode lastMode = Document::sInstance->fCanvasMode; - Document::sInstance->setCanvasMode(CanvasMode::pickFillStroke); + Document::sInstance->setCanvasMode(CanvasMode::pickFillStrokeEvent); auto conn = std::make_shared(); *conn = connect(scene, &Canvas::currentPickedColor, this, [this, conn, lastMode](const QColor &color) { From b68774f36d729723dd3e96cab31b4b1d4bb1ddbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Tue, 22 Oct 2024 21:38:27 +0200 Subject: [PATCH 10/23] Canvas: fix zoom on macOS #272 --- src/app/GUI/canvaswindow.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/GUI/canvaswindow.cpp b/src/app/GUI/canvaswindow.cpp index 9cf76a96c..5f7d8e982 100644 --- a/src/app/GUI/canvaswindow.cpp +++ b/src/app/GUI/canvaswindow.cpp @@ -312,6 +312,9 @@ void CanvasWindow::mouseMoveEvent(QMouseEvent *event) void CanvasWindow::wheelEvent(QWheelEvent *event) { +#ifdef Q_OS_MAC + if (event->angleDelta().y() == 0) { return; } +#endif if (!mCurrentCanvas) { return; } const auto ePos = event->position(); if (event->angleDelta().y() > 0) { From 7a4ee956529b1f37a219b873623d84d554ebeb1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Wed, 23 Oct 2024 21:41:42 +0200 Subject: [PATCH 11/23] Update .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 3ad3552c5..8ce46e957 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,6 @@ svgo-linux svgo-win.exe skia-build qt-* +sdk +build-release From 47c71cc0fc539eace5c5623a9c4e2fd5abf2820c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Wed, 23 Oct 2024 21:45:18 +0200 Subject: [PATCH 12/23] Update icons --- src/app/icons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/icons b/src/app/icons index c74c8879f..4bebcfba0 160000 --- a/src/app/icons +++ b/src/app/icons @@ -1 +1 @@ -Subproject commit c74c8879fbb69fe8a124d1a83a3d377dfaa779b0 +Subproject commit 4bebcfba0228c2d87e59db3013d3ef79508e05c6 From 4b84f4b3afe335791cdf714385443ad06734cbd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Fri, 25 Oct 2024 00:16:19 +0200 Subject: [PATCH 13/23] macOS: Multi-Touch support #276 Implement common gestures on macOS. - Pan (Slide two fingers, alt modifier to zoom) - Zoom in or out (Pinch with two fingers) - Smart Zoom (Double-tap with two fingers) Ref: https://github.com/friction2d/friction/issues/276 --- src/app/GUI/canvaswindow.cpp | 34 ++++++++++++++++++++++++++++++ src/app/GUI/canvaswindow.h | 8 ++++++- src/app/GUI/canvaswindowevents.cpp | 12 ++++++++--- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/app/GUI/canvaswindow.cpp b/src/app/GUI/canvaswindow.cpp index 5f7d8e982..c5e3896a9 100644 --- a/src/app/GUI/canvaswindow.cpp +++ b/src/app/GUI/canvaswindow.cpp @@ -313,6 +313,23 @@ void CanvasWindow::mouseMoveEvent(QMouseEvent *event) void CanvasWindow::wheelEvent(QWheelEvent *event) { #ifdef Q_OS_MAC + const bool alt = event->modifiers() & Qt::AltModifier; + if (!alt) { // handle event as pan gesture if not alt modifier + if (event->phase() == Qt::ScrollUpdate || + event->phase() == Qt::ScrollMomentum) { + auto pos = mPrevMousePos; + if (event->angleDelta().y() != 0) { + pos.setY(pos.y() + event->angleDelta().y()); + } + if (event->angleDelta().x() != 0) { + pos.setX(pos.x() + event->angleDelta().x()); + } + translateView(pos - mPrevMousePos); + mPrevMousePos = pos; + update(); + } + return; + } if (event->angleDelta().y() == 0) { return; } #endif if (!mCurrentCanvas) { return; } @@ -556,6 +573,23 @@ bool CanvasWindow::handleSelectAllKeyPress(QKeyEvent* event) return true; } +#ifdef Q_OS_MAC +bool CanvasWindow::handleNativeGestures(QNativeGestureEvent *event) +{ + if (!event || !mCurrentCanvas) { return false; } + const auto ePos = event->pos(); + if (event->gestureType() == Qt::ZoomNativeGesture) { + if (event->value() == 0) { return false; } + if (event->value() > 0) { zoomView(1.1, ePos); } + else { zoomView(0.9, ePos); } + update(); + } else if (event->gestureType() == Qt::SmartZoomNativeGesture) { + fitCanvasToSize(event->value() == 0 ? true : false); + } else { return false; } + return true; +} +#endif + // This does nothing ... /*bool CanvasWindow::handleShiftKeysKeyPress(QKeyEvent* event) { if(event->modifiers() & Qt::ControlModifier && diff --git a/src/app/GUI/canvaswindow.h b/src/app/GUI/canvaswindow.h index ec686339f..3e2b64011 100644 --- a/src/app/GUI/canvaswindow.h +++ b/src/app/GUI/canvaswindow.h @@ -27,6 +27,9 @@ #define CANVASWINDOW_H #include +#ifdef Q_OS_MAC +#include +#endif #include "widgets/glwindow.h" #include "singlewidgettarget.h" #include "misc/keyfocustarget.h" @@ -158,6 +161,9 @@ class CanvasWindow : public GLWindow, public KeyFocusTarget bool handleStartTransformKeyPress(const eKeyEvent &e); bool handleSelectAllKeyPress(QKeyEvent *event); //bool handleShiftKeysKeyPress(QKeyEvent *event); +#ifdef Q_OS_MAC + bool handleNativeGestures(QNativeGestureEvent *event); +#endif signals: void changeCanvasFrameRange(FrameRange); @@ -171,7 +177,7 @@ class CanvasWindow : public GLWindow, public KeyFocusTarget void zoomView(const qreal scaleBy, const QPointF &absOrigin); - void fitCanvasToSize(); + void fitCanvasToSize(const bool &fitWidth = false); void resetTransformation(); void zoomInView(); void zoomOutView(); diff --git a/src/app/GUI/canvaswindowevents.cpp b/src/app/GUI/canvaswindowevents.cpp index daddb35b2..df5c82804 100644 --- a/src/app/GUI/canvaswindowevents.cpp +++ b/src/app/GUI/canvaswindowevents.cpp @@ -69,7 +69,7 @@ void CanvasWindow::resizeEvent(QResizeEvent *e) GLWindow::resizeEvent(e); } -void CanvasWindow::fitCanvasToSize() +void CanvasWindow::fitCanvasToSize(const bool &fitWidth) { if (mFitToSizeBlocked) { mFitToSizeBlocked = false; @@ -83,7 +83,7 @@ void CanvasWindow::fitCanvasToSize() const qreal widHeight = height() * pixelRatio; const qreal widthScale = (widWidth - eSizesUI::widget) / canvasSize.width(); const qreal heightScale = (widHeight - eSizesUI::widget) / canvasSize.height(); - const qreal minScale = qMin(widthScale, heightScale); + const qreal minScale = fitWidth ? widthScale : qMin(widthScale, heightScale); translateView({(widWidth - canvasSize.width() * minScale) * 0.5, (widHeight - canvasSize.height() * minScale) * 0.5}); mViewTransform.scale(minScale, minScale); @@ -92,7 +92,7 @@ void CanvasWindow::fitCanvasToSize() void CanvasWindow::zoomInView() { - if (!mCurrentCanvas) { }return; + if (!mCurrentCanvas) { return; } const auto canvasSize = mCurrentCanvas->getCanvasSize(); mViewTransform.translate(canvasSize.width() * 0.5, canvasSize.height() * 0.5); mViewTransform.scale(1.1, 1.1); @@ -112,6 +112,12 @@ bool CanvasWindow::event(QEvent *e) { if (e->type() == QEvent::ShowToParent) { fitCanvasToSize(); } else if (e->type() == QEvent::Show) { KFT_setFocus(); } +#ifdef Q_OS_MAC + if (e->type() == QEvent::NativeGesture) { + auto g = dynamic_cast(e); + return handleNativeGestures(g); + } +#endif return QWidget::event(e); } From 7f531d03d9cdc58d20479063e0b56c8b058f1553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sat, 26 Oct 2024 00:18:51 +0200 Subject: [PATCH 14/23] macOS: fix canvas context menu --- src/app/GUI/canvaswindowevents.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/GUI/canvaswindowevents.cpp b/src/app/GUI/canvaswindowevents.cpp index df5c82804..12923f09f 100644 --- a/src/app/GUI/canvaswindowevents.cpp +++ b/src/app/GUI/canvaswindowevents.cpp @@ -115,7 +115,11 @@ bool CanvasWindow::event(QEvent *e) #ifdef Q_OS_MAC if (e->type() == QEvent::NativeGesture) { auto g = dynamic_cast(e); - return handleNativeGestures(g); + if (g->gestureType() == Qt::ZoomNativeGesture) { + return handleNativeGestures(g); + } else if (g->gestureType() == Qt::SmartZoomNativeGesture) { + handleNativeGestures(g); + } } #endif return QWidget::event(e); From 8b880d2342a2698663c588e2a2a04a447d4c9ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sat, 26 Oct 2024 01:06:57 +0200 Subject: [PATCH 15/23] macOS: fix zoom gesture origin --- src/app/GUI/canvaswindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/GUI/canvaswindow.cpp b/src/app/GUI/canvaswindow.cpp index c5e3896a9..d30d3168f 100644 --- a/src/app/GUI/canvaswindow.cpp +++ b/src/app/GUI/canvaswindow.cpp @@ -577,8 +577,8 @@ bool CanvasWindow::handleSelectAllKeyPress(QKeyEvent* event) bool CanvasWindow::handleNativeGestures(QNativeGestureEvent *event) { if (!event || !mCurrentCanvas) { return false; } - const auto ePos = event->pos(); if (event->gestureType() == Qt::ZoomNativeGesture) { + const auto ePos = event->localPos(); if (event->value() == 0) { return false; } if (event->value() > 0) { zoomView(1.1, ePos); } else { zoomView(0.9, ePos); } From 975d15dffcc9bc0ea1e9659a0c5f3ad33875e983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 27 Oct 2024 00:04:10 +0200 Subject: [PATCH 16/23] Create build_mac_sdk.sh --- src/scripts/build_mac_sdk.sh | 478 +++++++++++++++++++++++++++++++++++ 1 file changed, 478 insertions(+) create mode 100755 src/scripts/build_mac_sdk.sh diff --git a/src/scripts/build_mac_sdk.sh b/src/scripts/build_mac_sdk.sh new file mode 100755 index 000000000..161d8508e --- /dev/null +++ b/src/scripts/build_mac_sdk.sh @@ -0,0 +1,478 @@ +#!/bin/bash +# +# Friction - https://friction.graphics +# +# Copyright (c) Ole-André Rodlie and contributors +# +# This program 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 3 of the License, or +# (at your option) any later version. +# +# This program 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 this program. If not, see . +# + +set -e -x + +# keep in sync with other SDK's + +NINJA_V=1.11.1 +CMAKE_V=3.26.3 +NASM_V=2.14.02 +YASM_V=1.3.0 +PKGCONF_V=1.1.0 + +QT_V=5.15.15 +QSCINTILLA_V=2.14.1 + +LAME_V=3.100 +VPX_V=1.13.0 +OGG_V=1.3.5 +VORBIS_V=1.3.7 +THEORA_V=1.1.1 +XVID_V=1.3.4 +LSMASH_V=2.14.5 +X264_V=20180806-2245 +X265_V=3.5 +AOM_V=3.6.1 +FFMPEG_V=4.2.10 + +CWD=`pwd` +SDK=${SDK:-"${CWD}/sdk"} +SRC=${SDK}/src +DIST=${DIST:-"${CWD}/distfiles"} +MKJOBS=${MKJOBS:-2} +SRC_SUFFIX=tar.xz + +QMAKE_BIN=${SDK}/bin/qmake +PYTHON_BIN=${SDK}/bin/python +NINJA_BIN=${SDK}/bin/ninja +CMAKE_BIN=${SDK}/bin/cmake + +export PATH="${SDK}/bin:/usr/bin:/bin:/usr/sbin:/sbin" +export PKG_CONFIG_PATH="${SDK}/lib/pkgconfig" + +STATIC_CFLAGS="-fPIC" +DEFAULT_CFLAGS="-I${SDK}/include" +DEFAULT_LDFLAGS="-L${SDK}/lib" +COMMON_CONFIGURE="--prefix=${SDK}" +SHARED_CONFIGURE="${COMMON_CONFIGURE} --enable-shared --disable-static" +STATIC_CONFIGURE="${COMMON_CONFIGURE} --disable-shared --enable-static" +DEFAULT_CONFIGURE="${SHARED_CONFIGURE}" + +if [ ! -d "${SDK}" ]; then + mkdir -p "${SDK}/lib" + mkdir -p "${SDK}/bin" + mkdir -p "${SDK}/src" + (cd "${SDK}"; ln -sf lib lib64) + (cd "${SDK}/bin"; ln -sf /usr/bin/python3 python) +fi + +alias python="/usr/bin/python3" + +# ninja +if [ ! -f "${NINJA_BIN}" ]; then + cd ${SRC} + NINJA_SRC=ninja-${NINJA_V} + rm -rf ${NINJA_SRC} || true + tar xf ${DIST}/tools/${NINJA_SRC}.tar.gz + cd ${NINJA_SRC} + ./configure.py --bootstrap + cp -a ninja ${NINJA_BIN} +fi # ninja + +# cmake +if [ ! -f "${CMAKE_BIN}" ]; then + cd ${SRC} + CMAKE_SRC=cmake-${CMAKE_V} + rm -rf ${CMAKE_SRC} || true + tar xf ${DIST}/ffmpeg/${CMAKE_SRC}.tar.gz + cd ${CMAKE_SRC} + ./configure ${COMMON_CONFIGURE} --parallel=${MKJOBS} -- -DCMAKE_USE_OPENSSL=OFF + make -j${MKJOBS} + make install +fi # cmake + +# pkgconfig +if [ ! -f "${SDK}/bin/pkg-config" ]; then + cd ${SRC} + PKGCONF_SRC=pkgconf-${PKGCONF_V} + rm -rf ${PKGCONF_SRC} || true + tar xf ${DIST}/tools/${PKGCONF_SRC}.tar.xz + cd ${PKGCONF_SRC} + ./configure ${COMMON_CONFIGURE} + make -j${MKJOBS} + make install + (cd ${SDK}/bin ; ln -sf pkgconf pkg-config) +fi # pkgconfig + +# nasm +if [ ! -f "${SDK}/bin/nasm" ]; then + cd ${SRC} + NASM_SRC=nasm-${NASM_V} + rm -rf ${NASM_SRC} || true + tar xf ${DIST}/ffmpeg/${NASM_SRC}.tar.xz + cd ${NASM_SRC} + ./configure ${COMMON_CONFIGURE} + make -j${MKJOBS} + make install +fi # nasm + +# yasm +if [ ! -f "${SDK}/bin/yasm" ]; then + cd ${SRC} + YASM_SRC=yasm-${YASM_V} + rm -rf ${YASM_SRC} || true + tar xf ${DIST}/tools/${YASM_SRC}.tar.gz + cd ${YASM_SRC} + ./configure ${COMMON_CONFIGURE} + make -j${MKJOBS} + make install +fi # yasm + +# qt5 +if [ ! -f "${QMAKE_BIN}" ]; then + cd ${SRC} + QT_SRC="qt-everywhere-src-${QT_V}" + QT_TAR_SRC="qt-everywhere-opensource-src-${QT_V}" + if [ ! -d "${QT_SRC}" ]; then + tar xf ${DIST}/qt/${QT_TAR_SRC}.${SRC_SUFFIX} + fi + cd ${QT_SRC} + ./configure \ + -prefix ${SDK} \ + -c++std c++14 \ + -opengl desktop \ + -release \ + -shared \ + -opensource \ + -confirm-license \ + -optimize-size \ + -strip \ + -qt-pcre \ + -qt-zlib \ + -qt-libpng \ + -no-framework \ + -no-mtdev \ + -no-syslog \ + -no-pch \ + -no-glib \ + -no-dbus \ + -no-avx2 \ + -no-avx512 \ + -no-gif \ + -no-ico \ + -no-tiff \ + -no-webp \ + -no-jasper \ + -no-libjpeg \ + -no-ssl \ + -no-cups \ + -no-mng \ + -no-gstreamer \ + -no-alsa \ + -no-sql-db2 \ + -no-sql-ibase \ + -no-sql-mysql \ + -no-sql-oci \ + -no-sql-odbc \ + -no-sql-psql \ + -no-sql-sqlite2 \ + -no-sql-sqlite \ + -no-sql-tds \ + -no-gtk \ + -no-eglfs \ + -no-kms \ + -nomake examples \ + -nomake tests \ + -skip qt3d \ + -skip qtactiveqt \ + -skip qtcanvas3d \ + -skip qtcharts \ + -skip qtconnectivity \ + -skip qtdatavis3d \ + -skip qtdoc \ + -skip qtgamepad \ + -skip qtgraphicaleffects \ + -skip qtlocation \ + -skip qtlottie \ + -skip qtnetworkauth \ + -skip qtpurchasing \ + -skip qtquick3d \ + -skip qtquickcontrols \ + -skip qtquickcontrols2 \ + -skip qtremoteobjects \ + -skip qtscript \ + -skip qtscxml \ + -skip qtsensors \ + -skip qtserialbus \ + -skip qtserialport \ + -skip qtspeech \ + -skip qtvirtualkeyboard \ + -skip qtwebchannel \ + -skip qtwebengine \ + -skip qtwebglplugin \ + -skip qtwebsockets \ + -skip qtwebview \ + -skip qtxmlpatterns + make -j${MKJOBS} + make install +fi # qt5 + +# qscintilla +if [ ! -f "${SDK}/lib/libqscintilla2_qt5.dylib" ]; then + cd ${SRC} + QSC_SRC="QScintilla_src-${QSCINTILLA_V}" + rm -rf ${QSC_SRC} + tar xf ${DIST}/qt/${QSC_SRC}.tar.gz + cd ${QSC_SRC}/src + sed -i '' 's#!ios:QT += printsupport##' qscintilla.pro + sed -i '' 's#!ios:HEADERS += ./Qsci/qsciprinter.h##' qscintilla.pro + sed -i '' 's#!ios:SOURCES += qsciprinter.cpp##' qscintilla.pro + ${SDK}/bin/qmake CONFIG+=release + make -j${MKJOBS} + cp -a libqscintilla2_qt5* ${SDK}/lib/ + cp -a Qsci ${SDK}/include/ +fi # qscintilla + +# lame +if [ ! -f "${SDK}/lib/libmp3lame.dylib" ]; then + cd ${SRC} + LAME_SRC=lame-${LAME_V} + rm -rf ${LAME_SRC} || true + tar xf ${DIST}/ffmpeg/${LAME_SRC}.tar.gz + cd ${LAME_SRC} + patch -p0 < ${DIST}/ffmpeg/patch-lame-avoid_undefined_symbols_error.diff + CFLAGS="${DEFAULT_CFLAGS}" \ + CXXFLAGS="${DEFAULT_CFLAGS}" \ + LDFLAGS="${DEFAULT_LDFLAGS}" \ + ./configure ${DEFAULT_CONFIGURE} --disable-frontend --disable-gtktest --with-fileio=lame --enable-nasm + make -j${MKJOBS} + make install +fi # lame + +# libvpx +if [ ! -f "${SDK}/lib/libvpx.dylib" ]; then + cd ${SRC} + VPX_SRC=libvpx-${VPX_V} + rm -rf ${VPX_SRC} || true + tar xf ${DIST}/ffmpeg/libvpx-${VPX_V}.tar.gz + cd ${VPX_SRC} + patch -p0 < ${DIST}/ffmpeg/patch-vpx-Makefile.diff + patch -p0 < ${DIST}/ffmpeg/patch-vpx-configure.sh.diff + CFLAGS="${DEFAULT_CFLAGS}" \ + CXXFLAGS="${DEFAULT_CFLAGS}" \ + LDFLAGS="${DEFAULT_LDFLAGS}" \ + ./configure ${DEFAULT_CONFIGURE} \ + --enable-vp8 \ + --enable-vp9 \ + --enable-internal-stats \ + --enable-pic \ + --enable-postproc \ + --enable-multithread \ + --enable-runtime-cpu-detect \ + --enable-experimental \ + --enable-shared \ + --disable-install-docs \ + --disable-debug-libs \ + --disable-examples \ + --disable-unit-tests + make -j${MKJOBS} + make install +fi # libvpx + +# libogg +if [ ! -f "${SDK}/lib/libogg.dylib" ]; then + cd ${SRC} + OGG_SRC=libogg-${OGG_V} + rm -rf ${OGG_SRC} || true + tar xf ${DIST}/ffmpeg/${OGG_SRC}.tar.gz + cd ${OGG_SRC} + CFLAGS="${DEFAULT_CFLAGS}" \ + CXXFLAGS="${DEFAULT_CFLAGS}" \ + LDFLAGS="${DEFAULT_LDFLAGS}" \ + ./configure ${DEFAULT_CONFIGURE} + make -j${MKJOBS} + make install +fi # libogg + +# libvorbis +if [ ! -f "${SDK}/lib/libvorbis.dylib" ]; then + cd ${SRC} + VORBIS_SRC=libvorbis-${VORBIS_V} + rm -rf ${VORBIS_SRC} || true + tar xf ${DIST}/ffmpeg/${VORBIS_SRC}.tar.gz + cd ${VORBIS_SRC} + CFLAGS="${DEFAULT_CFLAGS}" \ + CXXFLAGS="${DEFAULT_CFLAGS}" \ + LDFLAGS="${DEFAULT_LDFLAGS}" \ + ./configure ${DEFAULT_CONFIGURE} + make -j${MKJOBS} + make install +fi # libvorbis + +# libtheora +if [ ! -f "${SDK}/lib/libtheora.dylib" ]; then + cd ${SRC} + THEORA_SRC=libtheora-${THEORA_V} + rm -rf ${THEORA_SRC} || true + tar xf ${DIST}/ffmpeg/${THEORA_SRC}.tar.gz + cd ${THEORA_SRC} + CFLAGS="${DEFAULT_CFLAGS}" \ + CXXFLAGS="${DEFAULT_CFLAGS}" \ + LDFLAGS="${DEFAULT_LDFLAGS}" \ + ./configure ${DEFAULT_CONFIGURE} --disable-examples --disable-sdltest + make -j${MKJOBS} + make install +fi # libtheora + +# xvidcore +if [ ! -f "${SDK}/lib/libxvidcore.4.dylib" ]; then + cd ${SRC} + rm -rf xvidcore || true + tar xf ${DIST}/ffmpeg/xvidcore-${XVID_V}.tar.gz + cd xvidcore/build/generic + CFLAGS="${DEFAULT_CFLAGS}" \ + CXXFLAGS="${DEFAULT_CFLAGS}" \ + LDFLAGS="${DEFAULT_LDFLAGS}" \ + ./configure ${COMMON_CONFIGURE} + make -j${MKJOBS} + make install +fi # xvidcore + +# liblsmash +#if [ ! -f "${SDK}/lib/liblsmash.dylib" ]; then +# cd ${SRC} +# LSMASH_SRC=l-smash-${LSMASH_V} +# rm -rf ${LSMASH_SRC} || true +# tar xf ${DIST}/ffmpeg/liblsmash-v${LSMASH_V}.tar.gz +# cd ${LSMASH_SRC} +# CFLAGS="${DEFAULT_CFLAGS}" \ +# CXXFLAGS="${DEFAULT_CFLAGS}" \ +# LDFLAGS="${DEFAULT_LDFLAGS}" \ +# ./configure ${DEFAULT_CONFIGURE} +# make -j${MKJOBS} +# make install +#fi # liblsmash + +# x264 +if [ ! -f "${SDK}/lib/libx264.dylib" ]; then + cd ${SRC} + X264_SRC=x264-snapshot-${X264_V} + rm -rf ${X264_SRC} || true + tar xf ${DIST}/ffmpeg/${X264_SRC}.tar.bz2 + cd ${X264_SRC} + CFLAGS="${DEFAULT_CFLAGS}" \ + CXXFLAGS="${DEFAULT_CFLAGS}" \ + LDFLAGS="${DEFAULT_LDFLAGS}" \ + ./configure ${COMMON_CONFIGURE} --enable-shared --disable-lavf --disable-swscale --disable-opencl --disable-cli + make -j${MKJOBS} + make install +fi # x264 + +# x265 +if [ ! -f "${SDK}/lib/libx265.dylib" ]; then + cd ${SRC} + X265_SRC=x265_${X265_V} + rm -rf ${X265_SRC} || true + tar xf ${DIST}/ffmpeg/${X265_SRC}.tar.gz + cd ${X265_SRC}/source + mkdir build && cd build + CFLAGS="${DEFAULT_CFLAGS}" \ + CXXFLAGS="${DEFAULT_CFLAGS}" \ + LDFLAGS="${DEFAULT_LDFLAGS}" \ + cmake \ + -DCMAKE_INSTALL_PREFIX=${SDK} \ + -DCMAKE_BUILD_TYPE=Release \ + -DENABLE_SHARED=ON \ + -DENABLE_CLI=OFF .. + make -j${MKJOBS} + make install +fi # x265 + +# aom +if [ ! -f "${SDK}/lib/libaom.dylib" ]; then + cd ${SRC} + AOM_SRC=libaom-${AOM_V} + rm -rf ${AOM_SRC} || true + tar xf ${DIST}/ffmpeg/${AOM_SRC}.tar.gz + cd ${AOM_SRC} + mkdir build2 && cd build2 + CFLAGS="${DEFAULT_CFLAGS}" \ + CXXFLAGS="${DEFAULT_CFLAGS}" \ + LDFLAGS="${DEFAULT_LDFLAGS}" \ + cmake \ + -DCMAKE_INSTALL_PREFIX=${SDK} \ + -DCMAKE_BUILD_TYPE=Release \ + -DENABLE_NASM=ON \ + -DENABLE_DOCS=OFF \ + -DENABLE_TESTS=OFF \ + -DENABLE_TESTDATA=OFF \ + -DENABLE_TOOLS=OFF \ + -DENABLE_EXAMPLES=OFF \ + -DCONFIG_AV1_HIGHBITDEPTH=0 \ + -DCONFIG_WEBM_IO=0 \ + -DBUILD_SHARED_LIBS=ON .. + make -j${MKJOBS} + make install +fi # aom + +if [ ! -f "${SDK}/lib/pkgconfig/libavcodec.pc" ]; then + cd ${SRC} + FFMPEG_SRC=ffmpeg-${FFMPEG_V} + rm -rf ${FFMPEG_SRC} || true + tar xf ${DIST}/ffmpeg/${FFMPEG_SRC}.tar.xz + cd ${FFMPEG_SRC} + CFLAGS="${DEFAULT_CFLAGS}" \ + CXXFLAGS="${DEFAULT_CFLAGS}" \ + LDFLAGS="${DEFAULT_LDFLAGS}" \ + ./configure ${SHARED_CONFIGURE} \ + --disable-securetransport \ + --disable-videotoolbox \ + --disable-libxcb \ + --disable-hwaccels \ + --disable-devices \ + --disable-openssl \ + --disable-sdl2 \ + --disable-xlib \ + --disable-libxcb \ + --disable-libv4l2 \ + --disable-alsa \ + --disable-network \ + --disable-programs \ + --disable-debug \ + --disable-doc \ + --enable-avresample \ + --enable-gpl \ + --enable-version3 \ + --disable-avisynth \ + --disable-gnutls \ + --disable-libass \ + --disable-libbluray \ + --disable-libbs2b \ + --disable-libcaca \ + --enable-libmp3lame \ + --disable-libopencore-amrnb \ + --disable-libopencore-amrwb \ + --disable-libopus \ + --disable-libspeex \ + --enable-libtheora \ + --disable-libvidstab \ + --disable-libvo-amrwbenc \ + --enable-libvorbis \ + --enable-libvpx \ + --enable-libx264 \ + --enable-libaom \ + --enable-libx265 \ + --enable-libxvid + make -j${MKJOBS} + make install +fi # ffmpeg + +echo "Friction macOS SDK done!" From e043cc7a3921002d233b28b744351c0ac0fdb3b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 27 Oct 2024 01:47:05 +0200 Subject: [PATCH 17/23] Update build_mac_sdk.sh --- src/scripts/build_mac_sdk.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/scripts/build_mac_sdk.sh b/src/scripts/build_mac_sdk.sh index 161d8508e..6c15c47c3 100755 --- a/src/scripts/build_mac_sdk.sh +++ b/src/scripts/build_mac_sdk.sh @@ -475,4 +475,9 @@ if [ ! -f "${SDK}/lib/pkgconfig/libavcodec.pc" ]; then make install fi # ffmpeg +(cd ${SDK}/lib ; +install_name_tool -change libvpx.8.dylib @rpath/libvpx.8.dylib libavformat.58.dylib +install_name_tool -change libvpx.8.dylib @rpath/libvpx.8.dylib libavcodec.58.dylib +) + echo "Friction macOS SDK done!" From d7bcea365bb3985b155a7909c6eedd887a3b77c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 27 Oct 2024 02:42:10 +0200 Subject: [PATCH 18/23] macOS: workaround audio issues Set sample rate to 22050 on macOS to avoid distorted/cracked audio, this is a workaround until we figure out what the real problem is. --- src/core/Sound/esoundsettings.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/Sound/esoundsettings.h b/src/core/Sound/esoundsettings.h index fb56e32dc..0e111e278 100644 --- a/src/core/Sound/esoundsettings.h +++ b/src/core/Sound/esoundsettings.h @@ -35,7 +35,11 @@ extern "C" { #include "../core_global.h" struct CORE_EXPORT eSoundSettingsData { +#ifdef Q_OS_MAC + int fSampleRate = 22050; +#else int fSampleRate = 44100; +#endif AVSampleFormat fSampleFormat = AV_SAMPLE_FMT_FLT; uint64_t fChannelLayout = AV_CH_LAYOUT_STEREO; From d86b4127c9049669365e6df1eba2248f171492be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 27 Oct 2024 17:44:45 +0100 Subject: [PATCH 19/23] Update docs --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 21260e038..a7230e21c 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 21260e038b5a0db8fe12bf0dbeb621427bb0bbb5 +Subproject commit a7230e21c0f656dc7da6a633bec9227c52b8591d From f5a9bfe75446022b51bac18934a159f2b05e4a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 27 Oct 2024 17:46:03 +0100 Subject: [PATCH 20/23] Update icons --- src/app/icons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/icons b/src/app/icons index 4bebcfba0..93cce63e2 160000 --- a/src/app/icons +++ b/src/app/icons @@ -1 +1 @@ -Subproject commit 4bebcfba0228c2d87e59db3013d3ef79508e05c6 +Subproject commit 93cce63e238d23b1ae1cf6982b7b7f56a99029e2 From 654902bcfcbf7c6703bd065f3ade063ad58b87c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 27 Oct 2024 17:53:06 +0100 Subject: [PATCH 21/23] Update colortoolbar.cpp Update icons. --- src/ui/widgets/colortoolbar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/widgets/colortoolbar.cpp b/src/ui/widgets/colortoolbar.cpp index 388a5ca1e..481cb33ec 100644 --- a/src/ui/widgets/colortoolbar.cpp +++ b/src/ui/widgets/colortoolbar.cpp @@ -109,9 +109,9 @@ void ColorToolBar::setupWidgets(Document &document) mColorFillAct = new QAction(QIcon::fromTheme("color"), tr("Fill"), this); - mColorStrokeAct = new QAction(QIcon::fromTheme("color"), + mColorStrokeAct = new QAction(QIcon::fromTheme("color_stroke"), tr("Stroke"), this); - mColorBackgroundAct = new QAction(QIcon::fromTheme("color"), + mColorBackgroundAct = new QAction(QIcon::fromTheme("color_background"), tr("Background"), this); mColorFillAct->setToolTip(tr("Fill Color")); From 9e2b34869e8bb800956330d10374b1973f0a66f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 27 Oct 2024 18:36:20 +0100 Subject: [PATCH 22/23] Update docs --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index a7230e21c..7fc583c4c 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit a7230e21c0f656dc7da6a633bec9227c52b8591d +Subproject commit 7fc583c4c526ef5d1a204df6a4ee985e66042b28 From 1403dbd4245e0c92c454a47f4e6938b1a6a6ccb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole-Andr=C3=A9=20Rodlie?= Date: Sun, 27 Oct 2024 22:45:01 +0100 Subject: [PATCH 23/23] macOS: scroll fixes --- src/app/GUI/graphboxeslist.cpp | 6 +++++- src/ui/widgets/colortoolbutton.cpp | 3 +++ src/ui/widgets/framescrollbar.cpp | 6 +++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/app/GUI/graphboxeslist.cpp b/src/app/GUI/graphboxeslist.cpp index f4444899c..b4fa5529a 100644 --- a/src/app/GUI/graphboxeslist.cpp +++ b/src/app/GUI/graphboxeslist.cpp @@ -482,7 +482,11 @@ void KeysView::graphDeletePressed() { mGPressedPoint = nullptr; } -void KeysView::graphWheelEvent(QWheelEvent *event) { +void KeysView::graphWheelEvent(QWheelEvent *event) +{ +#ifdef Q_OS_MAC + if (event->angleDelta().y() == 0) { return; } +#endif if(event->modifiers() & Qt::ControlModifier) { qreal valUnderMouse; qreal frame; diff --git a/src/ui/widgets/colortoolbutton.cpp b/src/ui/widgets/colortoolbutton.cpp index 0a93c208f..f85c52bf3 100644 --- a/src/ui/widgets/colortoolbutton.cpp +++ b/src/ui/widgets/colortoolbutton.cpp @@ -189,6 +189,9 @@ void ColorToolButton::mousePressEvent(QMouseEvent *e) void ColorToolButton::wheelEvent(QWheelEvent *e) { +#ifdef Q_OS_MAC + if (e->angleDelta().y() == 0) { return; } +#endif if (mColorTarget) { const bool ctrl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier); const bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); diff --git a/src/ui/widgets/framescrollbar.cpp b/src/ui/widgets/framescrollbar.cpp index b45fde581..8f8d8ea26 100644 --- a/src/ui/widgets/framescrollbar.cpp +++ b/src/ui/widgets/framescrollbar.cpp @@ -265,7 +265,11 @@ const QPair FrameScrollBar::getFrameOut() return {out.enabled, out.frame}; } -void FrameScrollBar::wheelEvent(QWheelEvent *event) { +void FrameScrollBar::wheelEvent(QWheelEvent *event) +{ +#ifdef Q_OS_MAC + if (event->angleDelta().y() == 0) { return; } +#endif if(mRange) { if(event->modifiers() & Qt::CTRL) { if(event->angleDelta().y() > 0) {