From 6d6bb9685672f1aa48a961311ef1e213a5f17682 Mon Sep 17 00:00:00 2001 From: MrStevns Date: Mon, 23 Sep 2024 18:46:16 +0200 Subject: [PATCH 01/10] iss: #1877 - Fix import image using camera transform not working --- app/src/importpositiondialog.cpp | 32 ++++++++--------------------- core_lib/src/interface/editor.cpp | 7 ------- core_lib/src/managers/viewmanager.h | 5 ----- 3 files changed, 9 insertions(+), 35 deletions(-) diff --git a/app/src/importpositiondialog.cpp b/app/src/importpositiondialog.cpp index e0b67291ab..eb3dcf3551 100644 --- a/app/src/importpositiondialog.cpp +++ b/app/src/importpositiondialog.cpp @@ -64,39 +64,25 @@ void ImportPositionDialog::didChangeComboBoxIndex(const int index) void ImportPositionDialog::changeImportView() { - mEditor->view()->setImportFollowsCamera(false); QTransform transform; if (mImportOption == ImportPosition::Type::CenterOfView) { QPointF centralPoint = mEditor->getScribbleArea()->getCentralPoint(); transform = transform.fromTranslate(centralPoint.x(), centralPoint.y()); - mEditor->view()->setImportView(transform); - QSettings settings(PENCIL2D, PENCIL2D); - settings.setValue(IMPORT_REPOSITION_TYPE, ui->cbImagePosition->currentIndex()); - return; } - else if (mImportOption == ImportPosition::Type::CenterOfCanvas) - { - transform = transform.fromTranslate(0, 0); - mEditor->view()->setImportView(transform); - QSettings settings(PENCIL2D, PENCIL2D); - settings.setValue(IMPORT_REPOSITION_TYPE, ui->cbImagePosition->currentIndex()); - return; - } - else if (mImportOption == ImportPosition::Type::CenterOfCamera) + else if (mImportOption == ImportPosition::Type::CenterOfCamera || mImportOption == ImportPosition::Type::CenterOfCameraFollowed) { LayerCamera* layerCam = static_cast(mEditor->layers()->getCameraLayerBelow(mEditor->currentLayerIndex())); Q_ASSERT(layerCam); - QRectF cameraRect = layerCam->getViewRect(); - transform = transform.fromTranslate(cameraRect.center().x(), cameraRect.center().y()); - mEditor->view()->setImportView(transform); - QSettings settings(PENCIL2D, PENCIL2D); - settings.setValue(IMPORT_REPOSITION_TYPE, ui->cbImagePosition->currentIndex()); - return; - } - Q_ASSERT(mImportOption == ImportPosition::Type::CenterOfCameraFollowed); - mEditor->view()->setImportFollowsCamera(true); + if (mImportOption == ImportPosition::Type::CenterOfCamera) { + KeyFrame* camKey = layerCam->getKeyFrameAt(mEditor->currentFrame()); + transform = layerCam->getViewAtFrame(camKey->pos()).inverted(); + } else { + transform = layerCam->getViewAtFrame(mEditor->currentFrame()).inverted(); + } + } + mEditor->view()->setImportView(transform); QSettings settings(PENCIL2D, PENCIL2D); settings.setValue(IMPORT_REPOSITION_TYPE, ui->cbImagePosition->currentIndex()); } diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index b997168995..49106c3795 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -1015,13 +1015,6 @@ Status Editor::importImage(const QString& filePath) DebugDetails dd; dd << QString("Raw file path: %1").arg(filePath); - if (view()->getImportFollowsCamera()) - { - LayerCamera* camera = static_cast(layers()->getLastCameraLayer()); - Q_ASSERT(camera); - QTransform transform = camera->getViewAtFrame(currentFrame()); - view()->setImportView(transform); - } switch (layer->type()) { case Layer::BITMAP: diff --git a/core_lib/src/managers/viewmanager.h b/core_lib/src/managers/viewmanager.h index 1c0009c4d5..3bd9cebd66 100644 --- a/core_lib/src/managers/viewmanager.h +++ b/core_lib/src/managers/viewmanager.h @@ -94,9 +94,6 @@ class ViewManager : public BaseManager QTransform getImportView() { return mImportView; } void setImportView(const QTransform& newView) { mImportView = newView; } - void setImportFollowsCamera(bool b) { mImportFollowsCamera = b; } - bool getImportFollowsCamera() { return mImportFollowsCamera; } - void forceUpdateViewTransform(); signals: @@ -126,8 +123,6 @@ class ViewManager : public BaseManager bool mOverlayThirds = false; bool mOverlayGoldenRatio = false; bool mOverlaySafeAreas = false; - - bool mImportFollowsCamera = false; }; #endif // VIEWMANAGER_H From 756949243af9f6a2e4b2ff5698c5ccf9b9b2bb15 Mon Sep 17 00:00:00 2001 From: MrStevns Date: Mon, 23 Sep 2024 18:49:49 +0200 Subject: [PATCH 02/10] Remove dead code --- core_lib/src/managers/viewmanager.cpp | 40 --------------------------- core_lib/src/managers/viewmanager.h | 14 ---------- 2 files changed, 54 deletions(-) diff --git a/core_lib/src/managers/viewmanager.cpp b/core_lib/src/managers/viewmanager.cpp index 9b85848ea8..fc01f17287 100644 --- a/core_lib/src/managers/viewmanager.cpp +++ b/core_lib/src/managers/viewmanager.cpp @@ -311,46 +311,6 @@ void ViewManager::flipVertical(bool b) } } -void ViewManager::setOverlayCenter(bool b) -{ - if (b != mOverlayCenter) - { - mOverlayCenter = b; - updateViewTransforms(); - emit viewChanged(); - } -} - -void ViewManager::setOverlayThirds(bool b) -{ - if (b != mOverlayThirds) - { - mOverlayThirds = b; - updateViewTransforms(); - emit viewChanged(); - } -} - -void ViewManager::setOverlayGoldenRatio(bool b) -{ - if (b != mOverlayGoldenRatio) - { - mOverlayGoldenRatio = b; - updateViewTransforms(); - emit viewChanged(); - } -} - -void ViewManager::setOverlaySafeAreas(bool b) -{ - if (b != mOverlaySafeAreas) - { - mOverlaySafeAreas = b; - updateViewTransforms(); - emit viewChanged(); - } -} - void ViewManager::setCanvasSize(QSize size) { mCanvasSize = size; diff --git a/core_lib/src/managers/viewmanager.h b/core_lib/src/managers/viewmanager.h index 3bd9cebd66..15d25d8e9e 100644 --- a/core_lib/src/managers/viewmanager.h +++ b/core_lib/src/managers/viewmanager.h @@ -77,18 +77,8 @@ class ViewManager : public BaseManager void flipHorizontal(bool b); void flipVertical(bool b); - void setOverlayCenter(bool b); - void setOverlayThirds(bool b); - void setOverlayGoldenRatio(bool b); - void setOverlaySafeAreas(bool b); - bool isFlipHorizontal() const { return mIsFlipHorizontal; } bool isFlipVertical() const { return mIsFlipVertical; } - bool getOverlayCenter() const { return mOverlayCenter; } - bool getOverlayThirds() const { return mOverlayThirds; } - bool getOverlayGoldenRatio() const { return mOverlayGoldenRatio; } - bool getOverlaySafeAreas() const { return mOverlaySafeAreas; } - void setCanvasSize(QSize size); QTransform getImportView() { return mImportView; } @@ -119,10 +109,6 @@ class ViewManager : public BaseManager bool mIsFlipHorizontal = false; bool mIsFlipVertical = false; - bool mOverlayCenter = false; - bool mOverlayThirds = false; - bool mOverlayGoldenRatio = false; - bool mOverlaySafeAreas = false; }; #endif // VIEWMANAGER_H From 9e83f758e8221a45825eda6962fa273891069197 Mon Sep 17 00:00:00 2001 From: MrStevns Date: Mon, 23 Sep 2024 19:20:50 +0200 Subject: [PATCH 03/10] Fix crash when importing and the scrubber is not on a keyframe --- app/src/importpositiondialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/importpositiondialog.cpp b/app/src/importpositiondialog.cpp index eb3dcf3551..3f736731d8 100644 --- a/app/src/importpositiondialog.cpp +++ b/app/src/importpositiondialog.cpp @@ -24,6 +24,7 @@ GNU General Public License for more details. #include "viewmanager.h" #include "layermanager.h" #include "scribblearea.h" +#include "camera.h" ImportPositionDialog::ImportPositionDialog(Editor* editor, QWidget *parent) : QDialog(parent), @@ -76,7 +77,7 @@ void ImportPositionDialog::changeImportView() Q_ASSERT(layerCam); if (mImportOption == ImportPosition::Type::CenterOfCamera) { - KeyFrame* camKey = layerCam->getKeyFrameAt(mEditor->currentFrame()); + KeyFrame* camKey = layerCam->getLastCameraAtFrame(mEditor->currentFrame(), 0); transform = layerCam->getViewAtFrame(camKey->pos()).inverted(); } else { transform = layerCam->getViewAtFrame(mEditor->currentFrame()).inverted(); From 04cff7b714dacdd6912e9a8864c502d03e279d66 Mon Sep 17 00:00:00 2001 From: MrStevns Date: Sat, 19 Oct 2024 15:09:23 +0200 Subject: [PATCH 04/10] Bump macOS runner to Ventura This should bring back 5.15 bottles for our macOS runner. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6397993aa4..0ad99eb39e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: env: ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true - name: Qt 5 / macOS x86_64 - os: macos-12 + os: macos-13 container: qt: 5 - name: Qt 5 / macOS arm64 @@ -59,7 +59,7 @@ jobs: container: { image: "ubuntu:22.04", options: --privileged } qt: 6 - name: Qt 6 / macOS x86_64 - os: macos-12 + os: macos-13 container: qt: 6 - name: Qt 6 / macOS arm64 From 4a73caa1e6db07d7749ea15cc4f692c1101eb37d Mon Sep 17 00:00:00 2001 From: MrStevns Date: Wed, 19 Feb 2025 20:22:32 +0100 Subject: [PATCH 05/10] Fix import to center of camera and camera followed not working --- app/src/importimageseqdialog.cpp | 8 ++--- app/src/importimageseqdialog.h | 5 +-- app/src/importpositiondialog.cpp | 25 +------------- app/src/importpositiondialog.h | 47 +++++++++++--------------- app/src/mainwindow2.cpp | 7 ++-- core_lib/core_lib.pro | 1 + core_lib/src/interface/editor.cpp | 43 +++++++++++++++++++---- core_lib/src/interface/editor.h | 5 +-- core_lib/src/managers/viewmanager.h | 4 --- core_lib/src/movieimporter.cpp | 6 ++-- core_lib/src/util/importpositiontype.h | 12 +++++++ 11 files changed, 87 insertions(+), 76 deletions(-) create mode 100644 core_lib/src/util/importpositiontype.h diff --git a/app/src/importimageseqdialog.cpp b/app/src/importimageseqdialog.cpp index 86c4515913..f3ba730f81 100644 --- a/app/src/importimageseqdialog.cpp +++ b/app/src/importimageseqdialog.cpp @@ -170,7 +170,7 @@ void ImportImageSeqDialog::setSpace(int number) uiOptionsBox->spaceSpinBox->setValue(number); } -void ImportImageSeqDialog::importArbitrarySequence() +void ImportImageSeqDialog::importArbitrarySequence(const ImportPositionType& importPositionType) { QStringList files = getFilePaths(); int number = getSpace(); @@ -189,7 +189,7 @@ void ImportImageSeqDialog::importArbitrarySequence() { QString strImgFileLower = strImgFile.toLower(); - Status st = mEditor->importImage(strImgFile); + Status st = mEditor->importImage(strImgFile, importPositionType); if (!st.ok()) { ErrorDialog errorDialog(st.title(), st.description(), st.details().html()); @@ -288,7 +288,7 @@ const PredefinedKeySetParams ImportImageSeqDialog::predefinedKeySetParams() cons return setParams; } -void ImportImageSeqDialog::importPredefinedSet() +void ImportImageSeqDialog::importPredefinedSet(const ImportPositionType& importPositionType) { PredefinedKeySet keySet = generatePredefinedKeySet(); @@ -310,7 +310,7 @@ void ImportImageSeqDialog::importPredefinedSet() const QString& filePath = keySet.filePathAt(i); mEditor->scrubTo(frameIndex); - Status st = mEditor->importImage(filePath); + Status st = mEditor->importImage(filePath, importPositionType); if (!st.ok()) { ErrorDialog errorDialog(st.title(), st.description(), st.details().html()); diff --git a/app/src/importimageseqdialog.h b/app/src/importimageseqdialog.h index 544ad9d943..537e0984c1 100644 --- a/app/src/importimageseqdialog.h +++ b/app/src/importimageseqdialog.h @@ -21,6 +21,7 @@ GNU General Public License for more details. #include "importexportdialog.h" #include "pencilerror.h" #include "predefinedsetmodel.h" +#include "importpositiontype.h" class Editor; @@ -52,8 +53,8 @@ class ImportImageSeqDialog : public ImportExportDialog ImportCriteria importCriteria = ImportCriteria::Arbitrary); ~ImportImageSeqDialog() override; - void importArbitrarySequence(); - void importPredefinedSet(); + void importArbitrarySequence(const ImportPositionType& importPositionType); + void importPredefinedSet(const ImportPositionType& importPositionType); int getSpace(); void setCore(Editor* editor) { mEditor = editor; } diff --git a/app/src/importpositiondialog.cpp b/app/src/importpositiondialog.cpp index 3f736731d8..06d1150fea 100644 --- a/app/src/importpositiondialog.cpp +++ b/app/src/importpositiondialog.cpp @@ -20,11 +20,7 @@ GNU General Public License for more details. #include #include #include "editor.h" -#include "layercamera.h" -#include "viewmanager.h" #include "layermanager.h" -#include "scribblearea.h" -#include "camera.h" ImportPositionDialog::ImportPositionDialog(Editor* editor, QWidget *parent) : QDialog(parent), @@ -60,30 +56,11 @@ ImportPositionDialog::~ImportPositionDialog() void ImportPositionDialog::didChangeComboBoxIndex(const int index) { - mImportOption = ImportPosition::getTypeFromIndex(index); + mImportOption = getTypeFromIndex(index); } void ImportPositionDialog::changeImportView() { - QTransform transform; - if (mImportOption == ImportPosition::Type::CenterOfView) - { - QPointF centralPoint = mEditor->getScribbleArea()->getCentralPoint(); - transform = transform.fromTranslate(centralPoint.x(), centralPoint.y()); - } - else if (mImportOption == ImportPosition::Type::CenterOfCamera || mImportOption == ImportPosition::Type::CenterOfCameraFollowed) - { - LayerCamera* layerCam = static_cast(mEditor->layers()->getCameraLayerBelow(mEditor->currentLayerIndex())); - Q_ASSERT(layerCam); - - if (mImportOption == ImportPosition::Type::CenterOfCamera) { - KeyFrame* camKey = layerCam->getLastCameraAtFrame(mEditor->currentFrame(), 0); - transform = layerCam->getViewAtFrame(camKey->pos()).inverted(); - } else { - transform = layerCam->getViewAtFrame(mEditor->currentFrame()).inverted(); - } - } - mEditor->view()->setImportView(transform); QSettings settings(PENCIL2D, PENCIL2D); settings.setValue(IMPORT_REPOSITION_TYPE, ui->cbImagePosition->currentIndex()); } diff --git a/app/src/importpositiondialog.h b/app/src/importpositiondialog.h index d77871a4aa..4c34f03b3d 100644 --- a/app/src/importpositiondialog.h +++ b/app/src/importpositiondialog.h @@ -19,6 +19,8 @@ GNU General Public License for more details. #include +#include "importpositiontype.h" + namespace Ui { class ImportPositionDialog; } @@ -29,44 +31,35 @@ class ImportPositionDialog : public QDialog { Q_OBJECT - struct ImportPosition { - - enum Type { - CenterOfView, - CenterOfCanvas, - CenterOfCamera, - CenterOfCameraFollowed, - None - }; - - static Type getTypeFromIndex(int index) { - switch (index) { - case 0: - return CenterOfView; - case 1: - return CenterOfCanvas; - case 2: - return CenterOfCamera; - case 3: - return CenterOfCameraFollowed; - default: - return None; - } - } - }; - public: explicit ImportPositionDialog(Editor* editor, QWidget *parent = nullptr); ~ImportPositionDialog(); + ImportPositionType importOption() const { return mImportOption; } + private slots: void didChangeComboBoxIndex(const int index); void changeImportView(); private: + static ImportPositionType getTypeFromIndex(int index) { + switch (index) { + case 0: + return ImportPositionType::CenterOfView; + case 1: + return ImportPositionType::CenterOfCanvas; + case 2: + return ImportPositionType::CenterOfCamera; + case 3: + return ImportPositionType::CenterOfCameraFollowed; + default: + return ImportPositionType::None; + } + } + Ui::ImportPositionDialog *ui; - ImportPosition::Type mImportOption = ImportPosition::None; + ImportPositionType mImportOption = ImportPositionType::None; Editor* mEditor = nullptr; }; diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index b4d78b4c74..727b27adaa 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -871,7 +871,8 @@ void MainWindow2::importImage() return; } - Status st = mEditor->importImage(strFilePath); + ImportPositionType importPositionType = positionDialog->importOption(); + Status st = mEditor->importImage(strFilePath, importPositionType); if (!st.ok()) { ErrorDialog errorDialog(st.title(), st.description(), st.details().html()); @@ -908,7 +909,7 @@ void MainWindow2::importImageSequence() return; } - imageSeqDialog->importArbitrarySequence(); + imageSeqDialog->importArbitrarySequence(positionDialog->importOption()); mSuppressAutoSaveDialog = false; } @@ -937,7 +938,7 @@ void MainWindow2::importPredefinedImageSet() return; } - imageSeqDialog->importPredefinedSet(); + imageSeqDialog->importPredefinedSet(positionDialog->importOption()); mSuppressAutoSaveDialog = false; } diff --git a/core_lib/core_lib.pro b/core_lib/core_lib.pro index 54e396635c..918751b997 100644 --- a/core_lib/core_lib.pro +++ b/core_lib/core_lib.pro @@ -92,6 +92,7 @@ HEADERS += \ src/util/colordictionary.h \ src/util/fileformat.h \ src/util/filetype.h \ + src/util/importpositiontype.h \ src/util/mathutils.h \ src/util/onionskinpainteroptions.h \ src/util/onionskinpaintstate.h \ diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index ef9e6a39e0..76415b1e18 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -26,6 +26,7 @@ GNU General Public License for more details. #include "vectorimage.h" #include "bitmapimage.h" #include "soundclip.h" +#include "camera.h" #include "layerbitmap.h" #include "layervector.h" #include "layercamera.h" @@ -911,7 +912,7 @@ void Editor::updateObject() emit updateLayerCount(); } -Status Editor::importBitmapImage(const QString& filePath) +Status Editor::importBitmapImage(const QString& filePath, const QTransform& importTransform) { QImageReader reader(filePath); @@ -954,8 +955,8 @@ Status Editor::importBitmapImage(const QString& filePath) status = Status(Status::FAIL, dd, tr("Import failed"), errorDesc); } - const QPoint pos(view()->getImportView().dx() - (img.width() / 2), - view()->getImportView().dy() - (img.height() / 2)); + const QPoint pos = importTransform.map(QPoint(-img.width() / 2, + -img.height() / 2)); if (!layer->keyExists(mFrame)) { @@ -1008,17 +1009,45 @@ Status Editor::importVectorImage(const QString& filePath) return status; } -Status Editor::importImage(const QString& filePath) +Status Editor::importImage(const QString& filePath, const ImportPositionType& importOption) { Layer* layer = layers()->currentLayer(); DebugDetails dd; dd << QString("Raw file path: %1").arg(filePath); + QTransform transform; + switch (importOption) + { + case ImportPositionType::CenterOfCamera: { + LayerCamera* layerCam = static_cast(layers()->getCameraLayerBelow(currentLayerIndex())); + Q_ASSERT(layerCam); + Camera* camKey = layerCam->getLastCameraAtFrame(currentFrame(), 0); + transform = layerCam->getViewAtFrame(camKey->pos()).inverted(); + break; + } + case ImportPositionType::CenterOfCameraFollowed: { + LayerCamera* camera = static_cast(layers()->getCameraLayerBelow(currentLayerIndex())); + Q_ASSERT(camera); + transform = camera->getViewAtFrame(currentFrame()).inverted(); + break; + } + case ImportPositionType::CenterOfView: { + QPointF centralPoint = mScribbleArea->getCentralPoint(); + transform = QTransform::fromTranslate(centralPoint.x(), centralPoint.y()); + break; + } + case ImportPositionType::CenterOfCanvas: + case ImportPositionType::None: { + transform = QTransform(); + break; + } + } + switch (layer->type()) { case Layer::BITMAP: - return importBitmapImage(filePath); + return importBitmapImage(filePath, transform); case Layer::VECTOR: return importVectorImage(filePath); @@ -1051,8 +1080,8 @@ Status Editor::importAnimatedImage(const QString& filePath, int frameSpacing, co } QImage img(reader.size(), QImage::Format_ARGB32_Premultiplied); - const QPoint pos(view()->getImportView().dx() - (img.width() / 2), - view()->getImportView().dy() - (img.height() / 2)); + const QPoint pos(view()->getView().dx() - (img.width() / 2), + view()->getView().dy() - (img.height() / 2)); int totalFrames = reader.imageCount(); while (reader.read(&img)) { diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index 61bd2a81d8..a2e24c28af 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -23,6 +23,7 @@ GNU General Public License for more details. #include #include "pencilerror.h" #include "pencildef.h" +#include "importpositiontype.h" #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) Q_MOC_INCLUDE("colormanager.h") @@ -173,7 +174,7 @@ class Editor : public QObject void clearCurrentFrame(); - Status importImage(const QString& filePath); + Status importImage(const QString& filePath, const ImportPositionType& importOption); Status importAnimatedImage(const QString& filePath, int frameSpacing, const std::function& progressChanged, const std::function& wasCanceled); void restoreKey(); @@ -236,7 +237,7 @@ class Editor : public QObject void resetAutoSaveCounter(); private: - Status importBitmapImage(const QString&); + Status importBitmapImage(const QString&, const QTransform& importTransform); Status importVectorImage(const QString&); void pasteToCanvas(BitmapImage* bitmapImage, int frameNumber); diff --git a/core_lib/src/managers/viewmanager.h b/core_lib/src/managers/viewmanager.h index 6e3023b9c2..8a286e682d 100644 --- a/core_lib/src/managers/viewmanager.h +++ b/core_lib/src/managers/viewmanager.h @@ -84,9 +84,6 @@ class ViewManager : public BaseManager bool isFlipVertical() const { return mIsFlipVertical; } void setCanvasSize(QSize size); - QTransform getImportView() { return mImportView; } - void setImportView(const QTransform& newView) { mImportView = newView; } - void forceUpdateViewTransform(); signals: @@ -102,7 +99,6 @@ class ViewManager : public BaseManager QTransform mViewCanvas; QTransform mViewCanvasInverse; QTransform mCentre; - QTransform mImportView; QPointF mTranslation = QPointF(); qreal mScaling = 1.0; diff --git a/core_lib/src/movieimporter.cpp b/core_lib/src/movieimporter.cpp index d9389bf5ae..93b2194b65 100644 --- a/core_lib/src/movieimporter.cpp +++ b/core_lib/src/movieimporter.cpp @@ -288,13 +288,13 @@ Status MovieImporter::generateFrames(std::function progress) { int currentFrame = mEditor->currentFrame(); if(layer->keyExists(mEditor->currentFrame())) { - mEditor->importImage(currentFile); + mEditor->importImage(currentFile, ImportPositionType::CenterOfView); } else { BitmapImage* bitmapImage = new BitmapImage(imgTopLeft, currentFile); if(imgTopLeft.isNull()) { - imgTopLeft.setX(static_cast(viewMan->getImportView().dx()) - bitmapImage->image()->width() / 2); - imgTopLeft.setY(static_cast(viewMan->getImportView().dy()) - bitmapImage->image()->height() / 2); + imgTopLeft.setX(static_cast(viewMan->getView().dx()) - bitmapImage->image()->width() / 2); + imgTopLeft.setY(static_cast(viewMan->getView().dy()) - bitmapImage->image()->height() / 2); bitmapImage->moveTopLeft(imgTopLeft); } layer->addKeyFrame(currentFrame, bitmapImage); diff --git a/core_lib/src/util/importpositiontype.h b/core_lib/src/util/importpositiontype.h new file mode 100644 index 0000000000..6b7437afcb --- /dev/null +++ b/core_lib/src/util/importpositiontype.h @@ -0,0 +1,12 @@ +#ifndef IMPORTPOSITIONTYPE_H +#define IMPORTPOSITIONTYPE_H + +enum class ImportPositionType { + CenterOfView, + CenterOfCanvas, + CenterOfCamera, + CenterOfCameraFollowed, + None +}; + +#endif // IMPORTPOSITIONTYPE_H From 58126918f342707393b4969e03cc7c3ce544f888 Mon Sep 17 00:00:00 2001 From: MrStevns Date: Wed, 19 Feb 2025 20:38:52 +0100 Subject: [PATCH 06/10] MovieImporter: Simplify generate frames --- core_lib/src/movieimporter.cpp | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/core_lib/src/movieimporter.cpp b/core_lib/src/movieimporter.cpp index 93b2194b65..9cdb787d64 100644 --- a/core_lib/src/movieimporter.cpp +++ b/core_lib/src/movieimporter.cpp @@ -274,33 +274,20 @@ Status MovieImporter::importMovieVideo(const QString &filePath, int fps, int fra Status MovieImporter::generateFrames(std::function progress) { - Layer* layer = mEditor->layers()->currentLayer(); Status status = Status::OK; int i = 1; QDir tempDir(mTempDir->path()); auto amountOfFrames = tempDir.count(); QString currentFile(tempDir.filePath(QString("%1.png").arg(i, 5, 10, QChar('0')))); - QPoint imgTopLeft; - - ViewManager* viewMan = mEditor->view(); while (QFileInfo::exists(currentFile)) { - int currentFrame = mEditor->currentFrame(); - if(layer->keyExists(mEditor->currentFrame())) { - mEditor->importImage(currentFile, ImportPositionType::CenterOfView); - } - else { - BitmapImage* bitmapImage = new BitmapImage(imgTopLeft, currentFile); - if(imgTopLeft.isNull()) { - imgTopLeft.setX(static_cast(viewMan->getView().dx()) - bitmapImage->image()->width() / 2); - imgTopLeft.setY(static_cast(viewMan->getView().dy()) - bitmapImage->image()->height() / 2); - bitmapImage->moveTopLeft(imgTopLeft); - } - layer->addKeyFrame(currentFrame, bitmapImage); - mEditor->layers()->notifyAnimationLengthChanged(); - mEditor->scrubTo(currentFrame + 1); + status = mEditor->importImage(currentFile, ImportPositionType::CenterOfCameraFollowed); + + if (!status.ok()) { + break; } + if (mCanceled) return Status::CANCELED; progress(qFloor(50 + i / static_cast(amountOfFrames) * 50)); i++; From 4ae7cb7969f7bf00022b2bd12e08f8942a71677a Mon Sep 17 00:00:00 2001 From: Jakob Gahde Date: Thu, 20 Feb 2025 16:36:48 +0100 Subject: [PATCH 07/10] Avoid taking const reference of enum (integer) --- app/src/importimageseqdialog.cpp | 4 ++-- app/src/importimageseqdialog.h | 4 ++-- core_lib/src/interface/editor.cpp | 2 +- core_lib/src/interface/editor.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/importimageseqdialog.cpp b/app/src/importimageseqdialog.cpp index f3ba730f81..6fded6ca28 100644 --- a/app/src/importimageseqdialog.cpp +++ b/app/src/importimageseqdialog.cpp @@ -170,7 +170,7 @@ void ImportImageSeqDialog::setSpace(int number) uiOptionsBox->spaceSpinBox->setValue(number); } -void ImportImageSeqDialog::importArbitrarySequence(const ImportPositionType& importPositionType) +void ImportImageSeqDialog::importArbitrarySequence(const ImportPositionType importPositionType) { QStringList files = getFilePaths(); int number = getSpace(); @@ -288,7 +288,7 @@ const PredefinedKeySetParams ImportImageSeqDialog::predefinedKeySetParams() cons return setParams; } -void ImportImageSeqDialog::importPredefinedSet(const ImportPositionType& importPositionType) +void ImportImageSeqDialog::importPredefinedSet(const ImportPositionType importPositionType) { PredefinedKeySet keySet = generatePredefinedKeySet(); diff --git a/app/src/importimageseqdialog.h b/app/src/importimageseqdialog.h index 537e0984c1..3c77b596a5 100644 --- a/app/src/importimageseqdialog.h +++ b/app/src/importimageseqdialog.h @@ -53,8 +53,8 @@ class ImportImageSeqDialog : public ImportExportDialog ImportCriteria importCriteria = ImportCriteria::Arbitrary); ~ImportImageSeqDialog() override; - void importArbitrarySequence(const ImportPositionType& importPositionType); - void importPredefinedSet(const ImportPositionType& importPositionType); + void importArbitrarySequence(ImportPositionType importPositionType); + void importPredefinedSet(ImportPositionType importPositionType); int getSpace(); void setCore(Editor* editor) { mEditor = editor; } diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 76415b1e18..7dc6f93c98 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -1009,7 +1009,7 @@ Status Editor::importVectorImage(const QString& filePath) return status; } -Status Editor::importImage(const QString& filePath, const ImportPositionType& importOption) +Status Editor::importImage(const QString& filePath, const ImportPositionType importOption) { Layer* layer = layers()->currentLayer(); diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index a2e24c28af..13771b72f7 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -174,7 +174,7 @@ class Editor : public QObject void clearCurrentFrame(); - Status importImage(const QString& filePath, const ImportPositionType& importOption); + Status importImage(const QString& filePath, ImportPositionType importOption); Status importAnimatedImage(const QString& filePath, int frameSpacing, const std::function& progressChanged, const std::function& wasCanceled); void restoreKey(); From 3120cb62b575896c720081d9d7d4aaeae1e5f19c Mon Sep 17 00:00:00 2001 From: MrStevns Date: Thu, 20 Feb 2025 21:22:56 +0100 Subject: [PATCH 08/10] Fix CenterOfCamera should use the import position keyframe, not the current --- app/src/importimageseqdialog.cpp | 8 ++++---- app/src/importimageseqdialog.h | 6 +++--- app/src/importpositiondialog.cpp | 6 +++++- app/src/importpositiondialog.h | 18 +++++++++--------- app/src/mainwindow2.cpp | 8 ++++---- core_lib/core_lib.pro | 2 +- core_lib/src/interface/editor.cpp | 16 ++++++++-------- core_lib/src/interface/editor.h | 4 ++-- core_lib/src/movieimporter.cpp | 4 +++- core_lib/src/util/importimageconfig.h | 18 ++++++++++++++++++ core_lib/src/util/importpositiontype.h | 12 ------------ 11 files changed, 57 insertions(+), 45 deletions(-) create mode 100644 core_lib/src/util/importimageconfig.h delete mode 100644 core_lib/src/util/importpositiontype.h diff --git a/app/src/importimageseqdialog.cpp b/app/src/importimageseqdialog.cpp index 6fded6ca28..b9fda5d1f3 100644 --- a/app/src/importimageseqdialog.cpp +++ b/app/src/importimageseqdialog.cpp @@ -170,7 +170,7 @@ void ImportImageSeqDialog::setSpace(int number) uiOptionsBox->spaceSpinBox->setValue(number); } -void ImportImageSeqDialog::importArbitrarySequence(const ImportPositionType importPositionType) +void ImportImageSeqDialog::importArbitrarySequence(const ImportImageConfig importImageConfig) { QStringList files = getFilePaths(); int number = getSpace(); @@ -189,7 +189,7 @@ void ImportImageSeqDialog::importArbitrarySequence(const ImportPositionType impo { QString strImgFileLower = strImgFile.toLower(); - Status st = mEditor->importImage(strImgFile, importPositionType); + Status st = mEditor->importImage(strImgFile, importImageConfig); if (!st.ok()) { ErrorDialog errorDialog(st.title(), st.description(), st.details().html()); @@ -288,7 +288,7 @@ const PredefinedKeySetParams ImportImageSeqDialog::predefinedKeySetParams() cons return setParams; } -void ImportImageSeqDialog::importPredefinedSet(const ImportPositionType importPositionType) +void ImportImageSeqDialog::importPredefinedSet(const ImportImageConfig importImageConfig) { PredefinedKeySet keySet = generatePredefinedKeySet(); @@ -310,7 +310,7 @@ void ImportImageSeqDialog::importPredefinedSet(const ImportPositionType importPo const QString& filePath = keySet.filePathAt(i); mEditor->scrubTo(frameIndex); - Status st = mEditor->importImage(filePath, importPositionType); + Status st = mEditor->importImage(filePath, importImageConfig); if (!st.ok()) { ErrorDialog errorDialog(st.title(), st.description(), st.details().html()); diff --git a/app/src/importimageseqdialog.h b/app/src/importimageseqdialog.h index 3c77b596a5..3107bbc106 100644 --- a/app/src/importimageseqdialog.h +++ b/app/src/importimageseqdialog.h @@ -21,7 +21,7 @@ GNU General Public License for more details. #include "importexportdialog.h" #include "pencilerror.h" #include "predefinedsetmodel.h" -#include "importpositiontype.h" +#include "importimageconfig.h" class Editor; @@ -53,8 +53,8 @@ class ImportImageSeqDialog : public ImportExportDialog ImportCriteria importCriteria = ImportCriteria::Arbitrary); ~ImportImageSeqDialog() override; - void importArbitrarySequence(ImportPositionType importPositionType); - void importPredefinedSet(ImportPositionType importPositionType); + void importArbitrarySequence(const ImportImageConfig importImageConfig); + void importPredefinedSet(const ImportImageConfig importImageConfig); int getSpace(); void setCore(Editor* editor) { mEditor = editor; } diff --git a/app/src/importpositiondialog.cpp b/app/src/importpositiondialog.cpp index 06d1150fea..8b97019127 100644 --- a/app/src/importpositiondialog.cpp +++ b/app/src/importpositiondialog.cpp @@ -56,11 +56,15 @@ ImportPositionDialog::~ImportPositionDialog() void ImportPositionDialog::didChangeComboBoxIndex(const int index) { - mImportOption = getTypeFromIndex(index); + mImportConfig.positionType = getTypeFromIndex(index); } void ImportPositionDialog::changeImportView() { + if (mImportConfig.positionType == ImportImageConfig::CenterOfCamera) { + mImportConfig.importFrame = mEditor->currentFrame(); + } + QSettings settings(PENCIL2D, PENCIL2D); settings.setValue(IMPORT_REPOSITION_TYPE, ui->cbImagePosition->currentIndex()); } diff --git a/app/src/importpositiondialog.h b/app/src/importpositiondialog.h index 4c34f03b3d..be363d8ec0 100644 --- a/app/src/importpositiondialog.h +++ b/app/src/importpositiondialog.h @@ -19,7 +19,7 @@ GNU General Public License for more details. #include -#include "importpositiontype.h" +#include "importimageconfig.h" namespace Ui { class ImportPositionDialog; @@ -35,31 +35,31 @@ class ImportPositionDialog : public QDialog explicit ImportPositionDialog(Editor* editor, QWidget *parent = nullptr); ~ImportPositionDialog(); - ImportPositionType importOption() const { return mImportOption; } + ImportImageConfig importConfig() const { return mImportConfig; } private slots: void didChangeComboBoxIndex(const int index); void changeImportView(); private: - static ImportPositionType getTypeFromIndex(int index) { + static ImportImageConfig::PositionType getTypeFromIndex(int index) { switch (index) { case 0: - return ImportPositionType::CenterOfView; + return ImportImageConfig::CenterOfView; case 1: - return ImportPositionType::CenterOfCanvas; + return ImportImageConfig::CenterOfCanvas; case 2: - return ImportPositionType::CenterOfCamera; + return ImportImageConfig::CenterOfCamera; case 3: - return ImportPositionType::CenterOfCameraFollowed; + return ImportImageConfig::CenterOfCameraFollowed; default: - return ImportPositionType::None; + return ImportImageConfig::None; } } Ui::ImportPositionDialog *ui; - ImportPositionType mImportOption = ImportPositionType::None; + ImportImageConfig mImportConfig; Editor* mEditor = nullptr; }; diff --git a/app/src/mainwindow2.cpp b/app/src/mainwindow2.cpp index 727b27adaa..7a886641d3 100644 --- a/app/src/mainwindow2.cpp +++ b/app/src/mainwindow2.cpp @@ -871,8 +871,8 @@ void MainWindow2::importImage() return; } - ImportPositionType importPositionType = positionDialog->importOption(); - Status st = mEditor->importImage(strFilePath, importPositionType); + ImportImageConfig importImageConfig = positionDialog->importConfig(); + Status st = mEditor->importImage(strFilePath, importImageConfig); if (!st.ok()) { ErrorDialog errorDialog(st.title(), st.description(), st.details().html()); @@ -909,7 +909,7 @@ void MainWindow2::importImageSequence() return; } - imageSeqDialog->importArbitrarySequence(positionDialog->importOption()); + imageSeqDialog->importArbitrarySequence(positionDialog->importConfig()); mSuppressAutoSaveDialog = false; } @@ -938,7 +938,7 @@ void MainWindow2::importPredefinedImageSet() return; } - imageSeqDialog->importPredefinedSet(positionDialog->importOption()); + imageSeqDialog->importPredefinedSet(positionDialog->importConfig()); mSuppressAutoSaveDialog = false; } diff --git a/core_lib/core_lib.pro b/core_lib/core_lib.pro index 918751b997..f76545784e 100644 --- a/core_lib/core_lib.pro +++ b/core_lib/core_lib.pro @@ -92,7 +92,7 @@ HEADERS += \ src/util/colordictionary.h \ src/util/fileformat.h \ src/util/filetype.h \ - src/util/importpositiontype.h \ + src/util/importimageconfig.h \ src/util/mathutils.h \ src/util/onionskinpainteroptions.h \ src/util/onionskinpaintstate.h \ diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 7dc6f93c98..35d92a27cc 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -1009,7 +1009,7 @@ Status Editor::importVectorImage(const QString& filePath) return status; } -Status Editor::importImage(const QString& filePath, const ImportPositionType importOption) +Status Editor::importImage(const QString& filePath, const ImportImageConfig importConfig) { Layer* layer = layers()->currentLayer(); @@ -1017,28 +1017,28 @@ Status Editor::importImage(const QString& filePath, const ImportPositionType imp dd << QString("Raw file path: %1").arg(filePath); QTransform transform; - switch (importOption) + switch (importConfig.positionType) { - case ImportPositionType::CenterOfCamera: { + case ImportImageConfig::CenterOfCamera: { LayerCamera* layerCam = static_cast(layers()->getCameraLayerBelow(currentLayerIndex())); Q_ASSERT(layerCam); - Camera* camKey = layerCam->getLastCameraAtFrame(currentFrame(), 0); + Camera* camKey = layerCam->getLastCameraAtFrame(importConfig.importFrame, 0); transform = layerCam->getViewAtFrame(camKey->pos()).inverted(); break; } - case ImportPositionType::CenterOfCameraFollowed: { + case ImportImageConfig::CenterOfCameraFollowed: { LayerCamera* camera = static_cast(layers()->getCameraLayerBelow(currentLayerIndex())); Q_ASSERT(camera); transform = camera->getViewAtFrame(currentFrame()).inverted(); break; } - case ImportPositionType::CenterOfView: { + case ImportImageConfig::CenterOfView: { QPointF centralPoint = mScribbleArea->getCentralPoint(); transform = QTransform::fromTranslate(centralPoint.x(), centralPoint.y()); break; } - case ImportPositionType::CenterOfCanvas: - case ImportPositionType::None: { + case ImportImageConfig::CenterOfCanvas: + case ImportImageConfig::None: { transform = QTransform(); break; } diff --git a/core_lib/src/interface/editor.h b/core_lib/src/interface/editor.h index 13771b72f7..8ccd0b49be 100644 --- a/core_lib/src/interface/editor.h +++ b/core_lib/src/interface/editor.h @@ -23,7 +23,7 @@ GNU General Public License for more details. #include #include "pencilerror.h" #include "pencildef.h" -#include "importpositiontype.h" +#include "importimageconfig.h" #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) Q_MOC_INCLUDE("colormanager.h") @@ -174,7 +174,7 @@ class Editor : public QObject void clearCurrentFrame(); - Status importImage(const QString& filePath, ImportPositionType importOption); + Status importImage(const QString& filePath, ImportImageConfig importConfig); Status importAnimatedImage(const QString& filePath, int frameSpacing, const std::function& progressChanged, const std::function& wasCanceled); void restoreKey(); diff --git a/core_lib/src/movieimporter.cpp b/core_lib/src/movieimporter.cpp index 9cdb787d64..b3c6b5f371 100644 --- a/core_lib/src/movieimporter.cpp +++ b/core_lib/src/movieimporter.cpp @@ -280,9 +280,11 @@ Status MovieImporter::generateFrames(std::function progress) auto amountOfFrames = tempDir.count(); QString currentFile(tempDir.filePath(QString("%1.png").arg(i, 5, 10, QChar('0')))); + ImportImageConfig importImageConfig; + importImageConfig.positionType = ImportImageConfig::CenterOfCameraFollowed; while (QFileInfo::exists(currentFile)) { - status = mEditor->importImage(currentFile, ImportPositionType::CenterOfCameraFollowed); + status = mEditor->importImage(currentFile, importImageConfig); if (!status.ok()) { break; diff --git a/core_lib/src/util/importimageconfig.h b/core_lib/src/util/importimageconfig.h new file mode 100644 index 0000000000..1486355819 --- /dev/null +++ b/core_lib/src/util/importimageconfig.h @@ -0,0 +1,18 @@ +#ifndef IMPORTPOSITIONCONFIG_H +#define IMPORTPOSITIONCONFIG_H + +struct ImportImageConfig +{ + enum PositionType { + CenterOfView, + CenterOfCanvas, + CenterOfCamera, + CenterOfCameraFollowed, + None + }; + + int importFrame = 1; + PositionType positionType = None; +}; + +#endif // IMPORTIMAGECONFIG_H diff --git a/core_lib/src/util/importpositiontype.h b/core_lib/src/util/importpositiontype.h deleted file mode 100644 index 6b7437afcb..0000000000 --- a/core_lib/src/util/importpositiontype.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef IMPORTPOSITIONTYPE_H -#define IMPORTPOSITIONTYPE_H - -enum class ImportPositionType { - CenterOfView, - CenterOfCanvas, - CenterOfCamera, - CenterOfCameraFollowed, - None -}; - -#endif // IMPORTPOSITIONTYPE_H From 865a06bcb9bb0fd7efcdcbfd99926f6441237b03 Mon Sep 17 00:00:00 2001 From: MrStevns Date: Thu, 20 Feb 2025 21:32:40 +0100 Subject: [PATCH 09/10] Get view of the current frame, not the current keyframe --- core_lib/src/interface/editor.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core_lib/src/interface/editor.cpp b/core_lib/src/interface/editor.cpp index 35d92a27cc..51916c3f42 100644 --- a/core_lib/src/interface/editor.cpp +++ b/core_lib/src/interface/editor.cpp @@ -1022,8 +1022,7 @@ Status Editor::importImage(const QString& filePath, const ImportImageConfig impo case ImportImageConfig::CenterOfCamera: { LayerCamera* layerCam = static_cast(layers()->getCameraLayerBelow(currentLayerIndex())); Q_ASSERT(layerCam); - Camera* camKey = layerCam->getLastCameraAtFrame(importConfig.importFrame, 0); - transform = layerCam->getViewAtFrame(camKey->pos()).inverted(); + transform = layerCam->getViewAtFrame(importConfig.importFrame).inverted(); break; } case ImportImageConfig::CenterOfCameraFollowed: { From 697e2c28c223b9d84cd2f6df715386c39c2c8a1e Mon Sep 17 00:00:00 2001 From: Jakob Gahde Date: Sun, 16 Mar 2025 22:03:52 +0100 Subject: [PATCH 10/10] Fix mismatched header guard and add missing licence header --- core_lib/src/util/importimageconfig.h | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/core_lib/src/util/importimageconfig.h b/core_lib/src/util/importimageconfig.h index 1486355819..a7d4e59cd6 100644 --- a/core_lib/src/util/importimageconfig.h +++ b/core_lib/src/util/importimageconfig.h @@ -1,5 +1,22 @@ -#ifndef IMPORTPOSITIONCONFIG_H -#define IMPORTPOSITIONCONFIG_H +/* + +Pencil2D - Traditional Animation Software +Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon +Copyright (C) 2012-2020 Matthew Chiawen Chang + +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; version 2 of the License. + +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. + +*/ + +#ifndef IMPORTIMAGECONFIG_H +#define IMPORTIMAGECONFIG_H struct ImportImageConfig {