diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index bb94180..55572ad 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,6 +1,5 @@ name: Bug report description: File a bug report to help us improve -labels: 'bug' body: - type: markdown attributes: @@ -39,9 +38,8 @@ body: description: You can find version information from the main menu bar [Help > About] within the software. multiple: false options: + - 1.7 - 1.6 - - 1.5 - - 1.4 - Nightly (Specify below) - Other (Specify below) validations: diff --git a/appveyor.yml b/appveyor.yml index eebb184..b2d19ac 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.7.0.{build} +version: 1.7.1.{build} pull_requests: do_not_increment_build_number: true skip_tags: true @@ -50,7 +50,7 @@ after_build: copy /Y ..\..\thirdparty\libmypaint\dist\64\libmypaint-1-4-0.dll %CONFIGURATION%\OpenToonz - copy /Y "C:\Tools\opencv\build\x64\vc15\bin\opencv_world460.dll" %CONFIGURATION%\OpenToonz + copy /Y "C:\Tools\opencv\build\x64\vc16\bin\opencv_world470.dll" %CONFIGURATION%\OpenToonz mkdir "%CONFIGURATION%\OpenToonz stuff" diff --git a/doc/how_to_build_linux.md b/doc/how_to_build_linux.md index f02cd37..c65e9f3 100644 --- a/doc/how_to_build_linux.md +++ b/doc/how_to_build_linux.md @@ -38,7 +38,7 @@ Notes: (it may include some useless packages) ``` -$ sudo dnf install gcc gcc-c++ automake git cmake boost boost-devel SuperLU SuperLU-devel lz4-devel lzma libusb-devel lzo-devel libjpeg-turbo-devel libGLEW glew-devel freeglut-devel freeglut freetype-devel libpng-devel qt5-qtbase-devel qt5-qtsvg qt5-qtsvg-devel qt5-qtscript qt5-qtscript-devel qt5-qttools qt5-qttools-devel qt5-qtmultimedia-devel blas blas-devel json-c-devel libtool intltool make qt5-qtmultimedia +$ sudo dnf install gcc gcc-c++ automake git cmake boost boost-devel SuperLU SuperLU-devel lz4-devel lzma libusb-devel lzo-devel libjpeg-turbo-devel libGLEW glew-devel freeglut-devel freeglut freetype-devel libpng-devel qt5-qtbase-devel qt5-qtsvg qt5-qtsvg-devel qt5-qtscript qt5-qtscript-devel qt5-qttools qt5-qttools-devel qt5-qtmultimedia-devel blas blas-devel json-c-devel libtool intltool make qt5-qtmultimedia turbojpeg-devel opencv-devel qt5-qttools-static qt5-qtserialport-devel ``` For newest versions of OS you may install libmypaint from repository and don't need to build it from source: diff --git a/stuff/config/qss/Blue/Blue.qss b/stuff/config/qss/Blue/Blue.qss index 2ee5fe4..73e6677 100644 --- a/stuff/config/qss/Blue/Blue.qss +++ b/stuff/config/qss/Blue/Blue.qss @@ -2372,6 +2372,7 @@ XsheetViewer { qproperty-XsheetPreviewButtonOnImage: url('../Default/imgs/white/x_prev_eye_on.svg'); qproperty-XsheetPreviewButtonBgOffColor: transparent; qproperty-XsheetPreviewButtonOffImage: url('../Default/imgs/white/x_prev_eye_off.svg'); + qproperty-XsheetUnifiedButtonTranspImage: url('../Default/imgs/white/x_prev_eye_transp.svg'); qproperty-XsheetCamstandButtonBgOnColor: #eb906b; qproperty-XsheetCamstandButtonOnImage: url('../Default/imgs/white/x_table_view_on.svg'); qproperty-XsheetCamstandButtonTranspImage: url('../Default/imgs/white/x_table_view_transp.svg'); @@ -2389,6 +2390,7 @@ XsheetViewer { qproperty-TimelinePreviewButtonOnImage: url('../Default/imgs/white/preview_small.svg'); qproperty-TimelinePreviewButtonBgOffColor: #414345; qproperty-TimelinePreviewButtonOffImage: url('none'); + qproperty-TimelineUnifiedButtonTranspImage: url('../Default/imgs/white/preview_trans_small.svg'); qproperty-TimelineCamstandButtonBgOnColor: #414345; qproperty-TimelineCamstandButtonOnImage: url('../Default/imgs/white/table_small.svg'); qproperty-TimelineCamstandButtonTranspImage: url('../Default/imgs/white/trans_small.svg'); diff --git a/stuff/config/qss/Dark/Dark.qss b/stuff/config/qss/Dark/Dark.qss index 7f6c51b..10652ea 100644 --- a/stuff/config/qss/Dark/Dark.qss +++ b/stuff/config/qss/Dark/Dark.qss @@ -2372,6 +2372,7 @@ XsheetViewer { qproperty-XsheetPreviewButtonOnImage: url('../Default/imgs/white/x_prev_eye_on.svg'); qproperty-XsheetPreviewButtonBgOffColor: transparent; qproperty-XsheetPreviewButtonOffImage: url('../Default/imgs/white/x_prev_eye_off.svg'); + qproperty-XsheetUnifiedButtonTranspImage: url('../Default/imgs/white/x_prev_eye_transp.svg'); qproperty-XsheetCamstandButtonBgOnColor: #eb906b; qproperty-XsheetCamstandButtonOnImage: url('../Default/imgs/white/x_table_view_on.svg'); qproperty-XsheetCamstandButtonTranspImage: url('../Default/imgs/white/x_table_view_transp.svg'); @@ -2389,6 +2390,7 @@ XsheetViewer { qproperty-TimelinePreviewButtonOnImage: url('../Default/imgs/white/preview_small.svg'); qproperty-TimelinePreviewButtonBgOffColor: #303030; qproperty-TimelinePreviewButtonOffImage: url('none'); + qproperty-TimelineUnifiedButtonTranspImage: url('../Default/imgs/white/preview_trans_small.svg'); qproperty-TimelineCamstandButtonBgOnColor: #303030; qproperty-TimelineCamstandButtonOnImage: url('../Default/imgs/white/table_small.svg'); qproperty-TimelineCamstandButtonTranspImage: url('../Default/imgs/white/trans_small.svg'); diff --git a/stuff/config/qss/Default/Default.qss b/stuff/config/qss/Default/Default.qss index e337927..f502d4d 100644 --- a/stuff/config/qss/Default/Default.qss +++ b/stuff/config/qss/Default/Default.qss @@ -2372,6 +2372,7 @@ XsheetViewer { qproperty-XsheetPreviewButtonOnImage: url('imgs/white/x_prev_eye_on.svg'); qproperty-XsheetPreviewButtonBgOffColor: transparent; qproperty-XsheetPreviewButtonOffImage: url('imgs/white/x_prev_eye_off.svg'); + qproperty-XsheetUnifiedButtonTranspImage: url('imgs/white/x_prev_eye_transp.svg'); qproperty-XsheetCamstandButtonBgOnColor: #eb906b; qproperty-XsheetCamstandButtonOnImage: url('imgs/white/x_table_view_on.svg'); qproperty-XsheetCamstandButtonTranspImage: url('imgs/white/x_table_view_transp.svg'); @@ -2389,6 +2390,7 @@ XsheetViewer { qproperty-TimelinePreviewButtonOnImage: url('imgs/white/preview_small.svg'); qproperty-TimelinePreviewButtonBgOffColor: #484848; qproperty-TimelinePreviewButtonOffImage: url('none'); + qproperty-TimelineUnifiedButtonTranspImage: url('imgs/white/preview_trans_small.svg'); qproperty-TimelineCamstandButtonBgOnColor: #484848; qproperty-TimelineCamstandButtonOnImage: url('imgs/white/table_small.svg'); qproperty-TimelineCamstandButtonTranspImage: url('imgs/white/trans_small.svg'); diff --git a/stuff/config/qss/Default/imgs/black/preview_trans_small.svg b/stuff/config/qss/Default/imgs/black/preview_trans_small.svg new file mode 100644 index 0000000..99ad099 --- /dev/null +++ b/stuff/config/qss/Default/imgs/black/preview_trans_small.svg @@ -0,0 +1,46 @@ + + + + + + diff --git a/stuff/config/qss/Default/imgs/black/x_prev_eye_transp.svg b/stuff/config/qss/Default/imgs/black/x_prev_eye_transp.svg new file mode 100644 index 0000000..72e7a33 --- /dev/null +++ b/stuff/config/qss/Default/imgs/black/x_prev_eye_transp.svg @@ -0,0 +1,70 @@ + + + + + + + diff --git a/stuff/config/qss/Default/imgs/white/preview_trans_small.svg b/stuff/config/qss/Default/imgs/white/preview_trans_small.svg new file mode 100644 index 0000000..abd0524 --- /dev/null +++ b/stuff/config/qss/Default/imgs/white/preview_trans_small.svg @@ -0,0 +1,46 @@ + + + + + + diff --git a/stuff/config/qss/Default/imgs/white/x_prev_eye_transp.svg b/stuff/config/qss/Default/imgs/white/x_prev_eye_transp.svg new file mode 100644 index 0000000..72e7a33 --- /dev/null +++ b/stuff/config/qss/Default/imgs/white/x_prev_eye_transp.svg @@ -0,0 +1,70 @@ + + + + + + + diff --git a/stuff/config/qss/Default/less/layouts/xsheet.less b/stuff/config/qss/Default/less/layouts/xsheet.less index 8863560..5d7cbca 100644 --- a/stuff/config/qss/Default/less/layouts/xsheet.less +++ b/stuff/config/qss/Default/less/layouts/xsheet.less @@ -170,6 +170,8 @@ XsheetViewer { qproperty-XsheetPreviewButtonBgOffColor: transparent; qproperty-XsheetPreviewButtonOffImage: url('@{img-url}/x_prev_eye_off.svg'); + qproperty-XsheetUnifiedButtonTranspImage: url('@{img-url}/x_prev_eye_transp.svg'); + qproperty-XsheetCamstandButtonBgOnColor: @xsheet-CamstandButtonBgOn-color; qproperty-XsheetCamstandButtonOnImage: url('@{img-url}/x_table_view_on.svg'); qproperty-XsheetCamstandButtonTranspImage: url('@{img-url}/x_table_view_transp.svg'); @@ -192,6 +194,8 @@ XsheetViewer { qproperty-TimelinePreviewButtonOnImage: url('@{img-url}/preview_small.svg'); qproperty-TimelinePreviewButtonBgOffColor: @bg; qproperty-TimelinePreviewButtonOffImage: url('none'); + + qproperty-TimelineUnifiedButtonTranspImage: url('@{img-url}/preview_trans_small.svg'); qproperty-TimelineCamstandButtonBgOnColor: @bg; qproperty-TimelineCamstandButtonOnImage: url('@{img-url}/table_small.svg'); diff --git a/stuff/config/qss/Light/Light.qss b/stuff/config/qss/Light/Light.qss index 8a0e464..ebe296f 100644 --- a/stuff/config/qss/Light/Light.qss +++ b/stuff/config/qss/Light/Light.qss @@ -2372,6 +2372,7 @@ XsheetViewer { qproperty-XsheetPreviewButtonOnImage: url('../Default/imgs/black/x_prev_eye_on.svg'); qproperty-XsheetPreviewButtonBgOffColor: transparent; qproperty-XsheetPreviewButtonOffImage: url('../Default/imgs/black/x_prev_eye_off.svg'); + qproperty-XsheetUnifiedButtonTranspImage: url('../Default/imgs/black/x_prev_eye_transp.svg'); qproperty-XsheetCamstandButtonBgOnColor: #ffa683; qproperty-XsheetCamstandButtonOnImage: url('../Default/imgs/black/x_table_view_on.svg'); qproperty-XsheetCamstandButtonTranspImage: url('../Default/imgs/black/x_table_view_transp.svg'); @@ -2389,6 +2390,7 @@ XsheetViewer { qproperty-TimelinePreviewButtonOnImage: url('../Default/imgs/black/preview_small.svg'); qproperty-TimelinePreviewButtonBgOffColor: #DBDBDB; qproperty-TimelinePreviewButtonOffImage: url('none'); + qproperty-TimelineUnifiedButtonTranspImage: url('../Default/imgs/black/preview_trans_small.svg'); qproperty-TimelineCamstandButtonBgOnColor: #DBDBDB; qproperty-TimelineCamstandButtonOnImage: url('../Default/imgs/black/table_small.svg'); qproperty-TimelineCamstandButtonTranspImage: url('../Default/imgs/black/trans_small.svg'); diff --git a/stuff/config/qss/Neutral/Neutral.qss b/stuff/config/qss/Neutral/Neutral.qss index f66f83d..7ac5da9 100644 --- a/stuff/config/qss/Neutral/Neutral.qss +++ b/stuff/config/qss/Neutral/Neutral.qss @@ -2372,6 +2372,7 @@ XsheetViewer { qproperty-XsheetPreviewButtonOnImage: url('../Default/imgs/black/x_prev_eye_on.svg'); qproperty-XsheetPreviewButtonBgOffColor: transparent; qproperty-XsheetPreviewButtonOffImage: url('../Default/imgs/black/x_prev_eye_off.svg'); + qproperty-XsheetUnifiedButtonTranspImage: url('../Default/imgs/black/x_prev_eye_transp.svg'); qproperty-XsheetCamstandButtonBgOnColor: #eb906b; qproperty-XsheetCamstandButtonOnImage: url('../Default/imgs/black/x_table_view_on.svg'); qproperty-XsheetCamstandButtonTranspImage: url('../Default/imgs/black/x_table_view_transp.svg'); @@ -2389,6 +2390,7 @@ XsheetViewer { qproperty-TimelinePreviewButtonOnImage: url('../Default/imgs/black/preview_small.svg'); qproperty-TimelinePreviewButtonBgOffColor: #808080; qproperty-TimelinePreviewButtonOffImage: url('none'); + qproperty-TimelineUnifiedButtonTranspImage: url('../Default/imgs/black/preview_trans_small.svg'); qproperty-TimelineCamstandButtonBgOnColor: #808080; qproperty-TimelineCamstandButtonOnImage: url('../Default/imgs/black/table_small.svg'); qproperty-TimelineCamstandButtonTranspImage: url('../Default/imgs/black/trans_small.svg'); diff --git a/stuff/library/textures/zottone_circle001.png b/stuff/library/textures/zottone_circle001.png new file mode 100644 index 0000000..7c58b26 Binary files /dev/null and b/stuff/library/textures/zottone_circle001.png differ diff --git a/stuff/library/textures/zottone_circle002.png b/stuff/library/textures/zottone_circle002.png new file mode 100644 index 0000000..825ec88 Binary files /dev/null and b/stuff/library/textures/zottone_circle002.png differ diff --git a/stuff/library/textures/zottone_cross001.png b/stuff/library/textures/zottone_cross001.png new file mode 100644 index 0000000..009b072 Binary files /dev/null and b/stuff/library/textures/zottone_cross001.png differ diff --git a/stuff/library/textures/zottone_cross002.png b/stuff/library/textures/zottone_cross002.png new file mode 100644 index 0000000..7074265 Binary files /dev/null and b/stuff/library/textures/zottone_cross002.png differ diff --git a/stuff/library/textures/zottone_cross003.png b/stuff/library/textures/zottone_cross003.png new file mode 100644 index 0000000..aa6aa05 Binary files /dev/null and b/stuff/library/textures/zottone_cross003.png differ diff --git a/stuff/library/textures/zottone_cross004.png b/stuff/library/textures/zottone_cross004.png new file mode 100644 index 0000000..44079d1 Binary files /dev/null and b/stuff/library/textures/zottone_cross004.png differ diff --git a/stuff/library/textures/zottone_cross005.png b/stuff/library/textures/zottone_cross005.png new file mode 100644 index 0000000..943c3ab Binary files /dev/null and b/stuff/library/textures/zottone_cross005.png differ diff --git a/stuff/library/textures/zottone_dash001.png b/stuff/library/textures/zottone_dash001.png new file mode 100644 index 0000000..9e7318e Binary files /dev/null and b/stuff/library/textures/zottone_dash001.png differ diff --git a/stuff/library/textures/zottone_dashd001.png b/stuff/library/textures/zottone_dashd001.png new file mode 100644 index 0000000..6857e67 Binary files /dev/null and b/stuff/library/textures/zottone_dashd001.png differ diff --git a/stuff/library/textures/zottone_dot001.png b/stuff/library/textures/zottone_dot001.png new file mode 100644 index 0000000..f06d16d Binary files /dev/null and b/stuff/library/textures/zottone_dot001.png differ diff --git a/stuff/library/textures/zottone_dot002.png b/stuff/library/textures/zottone_dot002.png new file mode 100644 index 0000000..7199c34 Binary files /dev/null and b/stuff/library/textures/zottone_dot002.png differ diff --git a/stuff/library/textures/zottone_dot003.png b/stuff/library/textures/zottone_dot003.png new file mode 100644 index 0000000..4124859 Binary files /dev/null and b/stuff/library/textures/zottone_dot003.png differ diff --git a/stuff/library/textures/zottone_dot005.png b/stuff/library/textures/zottone_dot005.png new file mode 100644 index 0000000..986d0e4 Binary files /dev/null and b/stuff/library/textures/zottone_dot005.png differ diff --git a/stuff/library/textures/zottone_dot006.png b/stuff/library/textures/zottone_dot006.png new file mode 100644 index 0000000..7ee171b Binary files /dev/null and b/stuff/library/textures/zottone_dot006.png differ diff --git a/stuff/library/textures/zottone_grid001.png b/stuff/library/textures/zottone_grid001.png new file mode 100644 index 0000000..83427b0 Binary files /dev/null and b/stuff/library/textures/zottone_grid001.png differ diff --git a/stuff/library/textures/zottone_grid002.png b/stuff/library/textures/zottone_grid002.png new file mode 100644 index 0000000..19f1ad8 Binary files /dev/null and b/stuff/library/textures/zottone_grid002.png differ diff --git a/stuff/library/textures/zottone_grid003.png b/stuff/library/textures/zottone_grid003.png new file mode 100644 index 0000000..71ef62e Binary files /dev/null and b/stuff/library/textures/zottone_grid003.png differ diff --git a/stuff/library/textures/zottone_grid004.png b/stuff/library/textures/zottone_grid004.png new file mode 100644 index 0000000..d2c9dd8 Binary files /dev/null and b/stuff/library/textures/zottone_grid004.png differ diff --git a/stuff/library/textures/zottone_grid005.png b/stuff/library/textures/zottone_grid005.png new file mode 100644 index 0000000..998842d Binary files /dev/null and b/stuff/library/textures/zottone_grid005.png differ diff --git a/stuff/library/textures/zottone_grid006.png b/stuff/library/textures/zottone_grid006.png new file mode 100644 index 0000000..6f558ec Binary files /dev/null and b/stuff/library/textures/zottone_grid006.png differ diff --git a/stuff/library/textures/zottone_grid007.png b/stuff/library/textures/zottone_grid007.png new file mode 100644 index 0000000..67306fc Binary files /dev/null and b/stuff/library/textures/zottone_grid007.png differ diff --git a/stuff/library/textures/zottone_grid020.png b/stuff/library/textures/zottone_grid020.png new file mode 100644 index 0000000..85b66ca Binary files /dev/null and b/stuff/library/textures/zottone_grid020.png differ diff --git a/stuff/library/textures/zottone_grid030.png b/stuff/library/textures/zottone_grid030.png new file mode 100644 index 0000000..4e6c135 Binary files /dev/null and b/stuff/library/textures/zottone_grid030.png differ diff --git a/stuff/library/textures/zottone_grid031.png b/stuff/library/textures/zottone_grid031.png new file mode 100644 index 0000000..803de10 Binary files /dev/null and b/stuff/library/textures/zottone_grid031.png differ diff --git a/stuff/library/textures/zottone_lined001.png b/stuff/library/textures/zottone_lined001.png new file mode 100644 index 0000000..749e084 Binary files /dev/null and b/stuff/library/textures/zottone_lined001.png differ diff --git a/stuff/library/textures/zottone_lined002.png b/stuff/library/textures/zottone_lined002.png new file mode 100644 index 0000000..8117663 Binary files /dev/null and b/stuff/library/textures/zottone_lined002.png differ diff --git a/stuff/library/textures/zottone_lined011.png b/stuff/library/textures/zottone_lined011.png new file mode 100644 index 0000000..3be6a54 Binary files /dev/null and b/stuff/library/textures/zottone_lined011.png differ diff --git a/stuff/library/textures/zottone_lined012.png b/stuff/library/textures/zottone_lined012.png new file mode 100644 index 0000000..bda0d1a Binary files /dev/null and b/stuff/library/textures/zottone_lined012.png differ diff --git a/stuff/library/textures/zottone_lineh001.png b/stuff/library/textures/zottone_lineh001.png new file mode 100644 index 0000000..f363260 Binary files /dev/null and b/stuff/library/textures/zottone_lineh001.png differ diff --git a/stuff/library/textures/zottone_lineh002.png b/stuff/library/textures/zottone_lineh002.png new file mode 100644 index 0000000..b0c1938 Binary files /dev/null and b/stuff/library/textures/zottone_lineh002.png differ diff --git a/stuff/library/textures/zottone_linev001.png b/stuff/library/textures/zottone_linev001.png new file mode 100644 index 0000000..2353eef Binary files /dev/null and b/stuff/library/textures/zottone_linev001.png differ diff --git a/stuff/library/textures/zottone_linev002.png b/stuff/library/textures/zottone_linev002.png new file mode 100644 index 0000000..181512e Binary files /dev/null and b/stuff/library/textures/zottone_linev002.png differ diff --git a/stuff/library/textures/zottone_wallbrick001.png b/stuff/library/textures/zottone_wallbrick001.png new file mode 100644 index 0000000..e99ba33 Binary files /dev/null and b/stuff/library/textures/zottone_wallbrick001.png differ diff --git a/stuff/library/textures/zottone_wave001.png b/stuff/library/textures/zottone_wave001.png new file mode 100644 index 0000000..1b07ceb Binary files /dev/null and b/stuff/library/textures/zottone_wave001.png differ diff --git a/stuff/library/textures/zottone_wave002.png b/stuff/library/textures/zottone_wave002.png new file mode 100644 index 0000000..d287658 Binary files /dev/null and b/stuff/library/textures/zottone_wave002.png differ diff --git a/toonz/cmake/BundleInfo.plist.in b/toonz/cmake/BundleInfo.plist.in index 8bc68f3..712cc6a 100644 --- a/toonz/cmake/BundleInfo.plist.in +++ b/toonz/cmake/BundleInfo.plist.in @@ -19,11 +19,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.7.0 + 1.7.1 CFBundleSignature ???? CFBundleVersion - 1.7 + 1.7.1 CSResourcesFileMapped LSRequiresCarbon diff --git a/toonz/sources/common/tsound/tsound.cpp b/toonz/sources/common/tsound/tsound.cpp index 1bb7c48..a887d90 100644 --- a/toonz/sources/common/tsound/tsound.cpp +++ b/toonz/sources/common/tsound/tsound.cpp @@ -82,7 +82,7 @@ TSoundTrackP TSoundTrack::create(TUINT32 sampleRate, int bitPerSample, int channelCount, TINT32 sampleCount, int sampleType) { TSoundTrackP st = 0; - int type = bitPerSample + channelCount; + int type = bitPerSample + channelCount; switch (type) { case TRK_M8: if (sampleType == TSound::INT) diff --git a/toonz/sources/include/orientation.h b/toonz/sources/include/orientation.h index 2c382b8..d758a26 100644 --- a/toonz/sources/include/orientation.h +++ b/toonz/sources/include/orientation.h @@ -93,6 +93,9 @@ enum class PredefinedRect { PREVIEW_LAYER_AREA, //! clickable area larger than preview icon, containing //! it PREVIEW_LAYER, + UNIFIEDVIEW_LAYER_AREA, //! used when unifying the preview and the camstand + //! toggles + UNIFIEDVIEW_LAYER, LOCK_AREA, //! clickable area larger than lock icon, containing it LOCK, //! the lock icon itself CAMERA_LOCK_AREA, //! lock area for the camera column diff --git a/toonz/sources/include/tfarmtask.h b/toonz/sources/include/tfarmtask.h index 23a1bcd..03751bc 100644 --- a/toonz/sources/include/tfarmtask.h +++ b/toonz/sources/include/tfarmtask.h @@ -135,6 +135,7 @@ public: QString getCommandLinePrgName() const; QString getCommandLineArguments() const; + QStringList getCommandLineArgumentsList() const; QString getCommandLine(bool isFarmTask = false) const; void parseCommandLine(QString commandLine); diff --git a/toonz/sources/include/toonz/preferences.h b/toonz/sources/include/toonz/preferences.h index eac1ace..957e7a1 100644 --- a/toonz/sources/include/toonz/preferences.h +++ b/toonz/sources/include/toonz/preferences.h @@ -396,6 +396,9 @@ public: bool isShowColumnNumbersEnabled() const { return getBoolValue(showColumnNumbers); } + bool isUnifyColumnVisibilityTogglesEnabled() const { + return getBoolValue(unifyColumnVisibilityToggles); + } bool isParentColorsInXsheetColumnEnabled() const { return getBoolValue(parentColorsInXsheetColumn); } @@ -418,6 +421,9 @@ public: bool isShowFrameNumberWithLettersEnabled() const { return getBoolValue(showFrameNumberWithLetters); } + bool isLinkColumnNameWithLevelEnabled() const { + return getBoolValue(linkColumnNameWithLevel); + } // Animation tab int getKeyframeType() const { return getIntValue(keyframeType); } diff --git a/toonz/sources/include/toonz/preferencesitemids.h b/toonz/sources/include/toonz/preferencesitemids.h index 4174fc3..1dd6454 100644 --- a/toonz/sources/include/toonz/preferencesitemids.h +++ b/toonz/sources/include/toonz/preferencesitemids.h @@ -132,6 +132,7 @@ enum PreferencesItemId { showXSheetToolbar, expandFunctionHeader, showColumnNumbers, + unifyColumnVisibilityToggles, parentColorsInXsheetColumn, highlightLineEverySecond, syncLevelRenumberWithXsheet, @@ -139,6 +140,7 @@ enum PreferencesItemId { currentColumnColor, levelNameDisplayType, showFrameNumberWithLetters, + linkColumnNameWithLevel, //---------- // Animation diff --git a/toonz/sources/include/toonz/txshlevelcolumn.h b/toonz/sources/include/toonz/txshlevelcolumn.h index e519264..6b50090 100644 --- a/toonz/sources/include/toonz/txshlevelcolumn.h +++ b/toonz/sources/include/toonz/txshlevelcolumn.h @@ -19,6 +19,7 @@ // forward declarations class TLevelColumnFx; class TXshCell; +class TXshLevel; //============================================================================= //! The TXshLevelColumn class provides a column of levels in xsheet and allows @@ -86,7 +87,8 @@ Return \b TFx. TFx *getFx() const override; // Used in TCellData::getNumbers - bool setNumbers(int row, int rowCount, const TXshCell cells[]); + bool setNumbers(int row, int rowCount, const TXshCell cells[], + TXshLevel *reservedLevel); private: // not implemented diff --git a/toonz/sources/include/toonzqt/dvdialog.h b/toonz/sources/include/toonzqt/dvdialog.h index f4af0e6..5917efd 100644 --- a/toonz/sources/include/toonzqt/dvdialog.h +++ b/toonz/sources/include/toonzqt/dvdialog.h @@ -261,7 +261,7 @@ public: public slots: void onCheckboxChanged(int checked); - void onButtonPressed(int id); + void onButtonClicked(int id); }; //----------------------------------------------------------------------------- diff --git a/toonz/sources/include/toonzqt/paramfield.h b/toonz/sources/include/toonzqt/paramfield.h index ea0ee85..9ecde50 100644 --- a/toonz/sources/include/toonzqt/paramfield.h +++ b/toonz/sources/include/toonzqt/paramfield.h @@ -613,8 +613,7 @@ namespace component { class MyTextEdit : public QTextEdit { Q_OBJECT public: - MyTextEdit(const QString &text, QWidget *parent = Q_NULLPTR) - : QTextEdit(text, parent) {} + MyTextEdit(const QString &text, QWidget *parent = Q_NULLPTR); protected: void keyPressEvent(QKeyEvent *event) override; diff --git a/toonz/sources/include/toonzqt/styleselection.h b/toonz/sources/include/toonzqt/styleselection.h index 0c561f2..4074c7d 100644 --- a/toonz/sources/include/toonzqt/styleselection.h +++ b/toonz/sources/include/toonzqt/styleselection.h @@ -98,7 +98,9 @@ public: void removeLink(); // get back the style from the studio palette (if linked) void getBackOriginalStyle(); - // return true if there is at least one linked style in the selection + + // return true if there is at least one linked style in the selection. + // link parent styles are not counted bool hasLinkedStyle(); }; diff --git a/toonz/sources/include/tversion.h b/toonz/sources/include/tversion.h index 591e8a0..b0069f4 100644 --- a/toonz/sources/include/tversion.h +++ b/toonz/sources/include/tversion.h @@ -19,8 +19,8 @@ public: private: const char *applicationName = "OpenToonz"; const float applicationVersion = 1.7f; - const float applicationRevision = 0; - const char *applicationNote = "RC"; + const float applicationRevision = 1; + const char *applicationNote = ""; }; std::string ToonzVersion::getAppName(void) { diff --git a/toonz/sources/tnztools/fullcolorbrushtool.cpp b/toonz/sources/tnztools/fullcolorbrushtool.cpp index 0204fe0..8675b4a 100644 --- a/toonz/sources/tnztools/fullcolorbrushtool.cpp +++ b/toonz/sources/tnztools/fullcolorbrushtool.cpp @@ -318,7 +318,7 @@ void FullColorBrushTool::handleMouseEvent(MouseEventType type, const TPointD &po bool shift = e.getModifiersMask() & TMouseEvent::SHIFT_KEY; bool control = e.getModifiersMask() & TMouseEvent::CTRL_KEY; - if ((control || shift) && type == ME_DOWN && e.button() == Qt::LeftButton && !m_started) { + if (shift && type == ME_DOWN && e.button() == Qt::LeftButton && !m_started) { m_modifierAssistants->drawOnly = true; m_inputmanager.clearModifiers(); m_inputmanager.addModifier( TInputModifierP(m_modifierLine.getPointer()) ); diff --git a/toonz/sources/tnztools/rgbpickertool.cpp b/toonz/sources/tnztools/rgbpickertool.cpp index 9737ea8..ba5838d 100644 --- a/toonz/sources/tnztools/rgbpickertool.cpp +++ b/toonz/sources/tnztools/rgbpickertool.cpp @@ -147,7 +147,7 @@ void setCurrentColor(const TPixel32 &color) { cs->setMainColor(color); cs->invalidateIcon(); - ph->notifyColorStyleChanged(); + ph->notifyColorStyleChanged(false); // per le palette animate int styleIndex = ph->getStyleIndex(); diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.cpp b/toonz/sources/tnztools/toonzrasterbrushtool.cpp index 180f9ea..08207af 100644 --- a/toonz/sources/tnztools/toonzrasterbrushtool.cpp +++ b/toonz/sources/tnztools/toonzrasterbrushtool.cpp @@ -1288,7 +1288,7 @@ void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos, } // Modifier to do straight line - if (e.isShiftPressed() || e.isCtrlPressed()) { + if (e.isShiftPressed()) { m_isStraight = true; m_firstPoint = pos; m_lastPoint = pos; diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.cpp b/toonz/sources/tnztools/toonzvectorbrushtool.cpp index a2e0d81..2f46d02 100644 --- a/toonz/sources/tnztools/toonzvectorbrushtool.cpp +++ b/toonz/sources/tnztools/toonzvectorbrushtool.cpp @@ -786,7 +786,7 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos, invalidateRect += TRectD(m_lastSnapPoint - snapThick, m_lastSnapPoint + snapThick); - if (e.isCtrlPressed()) { + if (e.isShiftPressed() && e.isCtrlPressed()) { TPointD m_firstPoint = m_track.getFirstPoint(); double denominator = m_lastSnapPoint.x - m_firstPoint.x; diff --git a/toonz/sources/tnztools/vectorselectiontool.cpp b/toonz/sources/tnztools/vectorselectiontool.cpp index a026b59..2a73d1e 100644 --- a/toonz/sources/tnztools/vectorselectiontool.cpp +++ b/toonz/sources/tnztools/vectorselectiontool.cpp @@ -416,12 +416,14 @@ void DragSelectionTool::UndoChangeStrokes::restoreRegions() const { void DragSelectionTool::UndoChangeStrokes::undo() const { transform(m_oldStrokes, m_oldBBox, m_oldCenter, m_oldDeformValues); restoreRegions(); + m_tool->notifyImageChanged(); } //----------------------------------------------------------------------------- void DragSelectionTool::UndoChangeStrokes::redo() const { transform(m_newStrokes, m_newBBox, m_newCenter, m_newDeformValues); + m_tool->notifyImageChanged(); } //----------------------------------------------------------------------------- @@ -521,6 +523,7 @@ void UndoChangeOutlineStyle::transform( void UndoChangeOutlineStyle::undo() const { transform(m_oldOptions, m_oldBBox); TTool::getApplication()->getCurrentTool()->notifyToolChanged(); + m_tool->notifyImageChanged(); } //----------------------------------------------------------------------------- @@ -528,6 +531,7 @@ void UndoChangeOutlineStyle::undo() const { void UndoChangeOutlineStyle::redo() const { transform(m_newOptions, m_newBBox); TTool::getApplication()->getCurrentTool()->notifyToolChanged(); + m_tool->notifyImageChanged(); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/tnztools/vectortapetool.cpp b/toonz/sources/tnztools/vectortapetool.cpp index 808e05b..1498ef3 100644 --- a/toonz/sources/tnztools/vectortapetool.cpp +++ b/toonz/sources/tnztools/vectortapetool.cpp @@ -23,7 +23,6 @@ #include "tenv.h" // For Qt translation support #include -#include using namespace ToolUtils; @@ -177,8 +176,6 @@ public: class VectorTapeTool final : public TTool { Q_DECLARE_TR_FUNCTIONS(VectorTapeTool) - bool m_draw; - bool m_secondPoint; int m_strokeIndex1, m_strokeIndex2; double m_w1, m_w2, m_pixelSize; @@ -203,7 +200,6 @@ public: , m_w1(-1.0) , m_w2(-1.0) , m_pixelSize(1) - , m_draw(false) , m_smooth("Smooth", false) // W_ToolOptions_Smooth , m_joinStrokes("JoinStrokes", false) , m_mode("Mode") @@ -277,7 +273,6 @@ public: void draw() override { TVectorImageP vi(getImage(false)); - if (!m_draw) return; if (!vi) return; // TAffine viewMatrix = getViewer()->getViewMatrix(); @@ -326,10 +321,6 @@ public: TVectorImageP vi(getImage(false)); if (!vi) return; - // BUTTA e rimetti (Dava problemi con la penna) - //if (!m_draw) return; // Questa riga potrebbe non essere messa - // m_draw=true; //Perche'??? Non basta dargli true in onEnter?? - if (m_type.getValue() == RECT) return; double minDistance2 = 10000000000.; @@ -737,23 +728,11 @@ public: void onEnter() override { // getApplication()->editImage(); - m_draw = true; m_selectionRect = TRectD(); m_startRect = TPointD(); } - void onLeave() override { - m_draw = false; - // m_strokeIndex1=-1; - } - void onActivate() override { - // enable drawing if we are in a scene viewer - QWidget *focusWidget = QApplication::focusWidget(); - if (focusWidget && - QString(focusWidget->metaObject()->className()) == "SceneViewer") - m_draw = true; - if (!m_firstTime) return; std::wstring s = ::to_wstring(TapeMode.getValue()); diff --git a/toonz/sources/toonz/CMakeLists.txt b/toonz/sources/toonz/CMakeLists.txt index 925afe4..1d46132 100644 --- a/toonz/sources/toonz/CMakeLists.txt +++ b/toonz/sources/toonz/CMakeLists.txt @@ -1,4 +1,4 @@ -set(VERSION 1.7) +set(VERSION 1.7.1) set(MOC_HEADERS addfilmstripframespopup.h diff --git a/toonz/sources/toonz/batches.cpp b/toonz/sources/toonz/batches.cpp index a0877c1..a0bd2d3 100644 --- a/toonz/sources/toonz/batches.cpp +++ b/toonz/sources/toonz/batches.cpp @@ -244,17 +244,7 @@ commandline += " -id " + task->m_id;*/ } process->setProgram(task->getCommandLinePrgName()); -#if defined(_WIN32) - process->setNativeArguments(task->getCommandLineArguments()); -#else -#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) - process->setArguments( - task->getCommandLineArguments().split(" ", Qt::SkipEmptyParts)); -#else - process->setArguments( - task->getCommandLineArguments().split(" ", QString::SkipEmptyParts)); -#endif -#endif + process->setArguments(task->getCommandLineArgumentsList()); process->start(); process->waitForFinished(-1); diff --git a/toonz/sources/toonz/cameracapturelevelcontrol.cpp b/toonz/sources/toonz/cameracapturelevelcontrol.cpp index 3714154..b9746fd 100644 --- a/toonz/sources/toonz/cameracapturelevelcontrol.cpp +++ b/toonz/sources/toonz/cameracapturelevelcontrol.cpp @@ -399,4 +399,35 @@ void CameraCaptureLevelControl::computeLut() { p[i] = (uchar)std::floor(value * maxChannelValueF); } +} + +//----------------------------------------------------------------------------- + +void CameraCaptureLevelControl::getValues(int& black, int& white, + int& threshold, double& gamma) { + black = m_histogram->black(); + white = m_histogram->white(); + threshold = m_histogram->threshold(); + gamma = (double)m_histogram->gamma(); +} + +//----------------------------------------------------------------------------- + +void CameraCaptureLevelControl::setValues(const int black, const int white, + const int threshold, + const double gamma, + const bool color_grayscale) { + m_whiteFld->setRange(black + 2, 255); + m_blackFld->setRange(0, white - 2); + m_blackFld->setValue(black); + m_whiteFld->setValue(white); + m_gammaFld->setValue(gamma); + m_thresholdFld->setValue(threshold); + + m_histogram->setValues(m_blackFld->getValue(), m_whiteFld->getValue(), + m_gammaFld->getValue()); + m_histogram->setThreshold(m_thresholdFld->getValue()); + + setMode(color_grayscale); + computeLut(); } \ No newline at end of file diff --git a/toonz/sources/toonz/cameracapturelevelcontrol.h b/toonz/sources/toonz/cameracapturelevelcontrol.h index 5e3c191..f89031a 100644 --- a/toonz/sources/toonz/cameracapturelevelcontrol.h +++ b/toonz/sources/toonz/cameracapturelevelcontrol.h @@ -89,6 +89,11 @@ public: void adjustLevel(cv::Mat& image); void binarize(cv::Mat& image); + // for saving / loading default + void getValues(int& black, int& white, int& threshold, double& gamma); + void setValues(const int black, const int white, const int threshold, + const double gamma, const bool color_grayscale); + protected slots: void onHistogramValueChanged(int itemId); void onFieldChanged(); diff --git a/toonz/sources/toonz/celldata.cpp b/toonz/sources/toonz/celldata.cpp index 709f2fd..bee5fc1 100644 --- a/toonz/sources/toonz/celldata.cpp +++ b/toonz/sources/toonz/celldata.cpp @@ -11,6 +11,12 @@ #include "toonz/tcolumnfx.h" #include "toonz/fxdag.h" #include "toonz/txshlevelcolumn.h" +#include "toonz/preferences.h" +#include "toonz/tstageobject.h" +#include "tapp.h" +#include "toonz/tscenehandle.h" +#include "toonz/toonzscene.h" +#include "toonz/levelset.h" //----------------------------------------------------------------------------- @@ -106,15 +112,35 @@ bool TCellData::getCells(TXsheet *xsh, int r0, int c0, int &r1, int &c1, bool TCellData::getNumbers(TXsheet *xsh, int r0, int c0, int &r1, int &c1) const { - r1 = r0 + m_rowCount - 1; - bool oneToMulti = m_colCount == 1 && c0 < c1; + r1 = r0 + m_rowCount - 1; + bool oneToMulti = m_colCount == 1 && c0 < c1; if (!oneToMulti) c1 = c0 + m_colCount - 1; bool cellSet = false; for (int c = c0; c <= c1; c++) { - TXshColumn *column = xsh->getColumn(c); - if (!column || column->isEmpty()) continue; + TXshColumn *column = xsh->getColumn(c); + TXshLevel *reservedLevel = nullptr; + if (!column) continue; + if (column->isEmpty()) { + if (Preferences::instance()->isLinkColumnNameWithLevelEnabled() && + xsh->getStageObject(TStageObjectId::ColumnId(c)) + ->hasSpecifiedName()) { + std::string columnName = + xsh->getStageObject(TStageObjectId::ColumnId(c))->getName(); + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + TLevelSet *levelSet = scene->getLevelSet(); + reservedLevel = levelSet->getLevel(to_wstring(columnName)); + if (!reservedLevel) continue; + // connect to xsheet + if (!column->getPaletteColumn()) { + TFx *fx = column->getFx(); + if (fx) xsh->getFxDag()->addToXsheet(fx); + } + + } else + continue; + } TXshLevelColumn *levelColumn = column->getLevelColumn(); if (!levelColumn) continue; @@ -125,8 +151,8 @@ bool TCellData::getNumbers(TXsheet *xsh, int r0, int c0, int &r1, if (!canChange(column, sourceColIndex)) continue; - bool isSet = levelColumn->setNumbers(r0, m_rowCount, - &cells[sourceColIndex * m_rowCount]); + bool isSet = levelColumn->setNumbers( + r0, m_rowCount, &cells[sourceColIndex * m_rowCount], reservedLevel); cellSet = cellSet || isSet; } @@ -194,7 +220,7 @@ void TCellData::cloneZeraryFx(int index, std::vector &cells) const { newFxLevel->setColumn(newFxColumn); // replace the zerary fx cells by the new fx int r; - for (r = firstNotEmptyIndex; r < (index + 1) * m_rowCount; r++) + for (r = firstNotEmptyIndex; r < (index + 1) * m_rowCount; r++) cells[r] = TXshCell(newFxLevel, m_cells[r].getFrameId()); } } diff --git a/toonz/sources/toonz/cellselection.cpp b/toonz/sources/toonz/cellselection.cpp index cf127b1..0f5c6f1 100644 --- a/toonz/sources/toonz/cellselection.cpp +++ b/toonz/sources/toonz/cellselection.cpp @@ -58,6 +58,7 @@ #include "tools/strokeselection.h" #include "toonz/sceneproperties.h" #include "toutputproperties.h" +#include "toonz/tstageobjectcmd.h" // TnzCore includes #include "timagecache.h" @@ -217,13 +218,17 @@ class PasteCellsUndo final : public TUndo { TCellData *m_data; std::vector m_areOldColumnsEmpty; bool m_containsSoundColumn; + std::map m_oldEmptyColumnNames; public: PasteCellsUndo(int r0, int c0, int r1, int c1, int oldR0, int oldC0, int oldR1, int oldC1, const std::vector &areColumnsEmpty, - bool containsSoundColumn) + bool containsSoundColumn, + const std::map &oldEmptyColumnNames = + std::map()) : m_areOldColumnsEmpty(areColumnsEmpty) - , m_containsSoundColumn(containsSoundColumn) { + , m_containsSoundColumn(containsSoundColumn) + , m_oldEmptyColumnNames(oldEmptyColumnNames) { m_data = new TCellData(); TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); m_data->setCells(xsh, r0, c0, r1, c1); @@ -246,13 +251,18 @@ public: int oldR0, oldC0, oldR1, oldC1; m_oldSelection->getSelectedCells(oldR0, oldC0, oldR1, oldC1); + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + for (const auto &item : m_oldEmptyColumnNames) { + xsh->getStageObject(TStageObjectId::ColumnId(item.first)) + ->setName(item.second); + } + int c0BeforeCut = c0; int c1BeforeCut = c1; // Cut delle celle che sono in newSelection cutCellsWithoutUndo(r0, c0, r1, c1); // Se le colonne erano vuote le resetto (e' necessario farlo per le colonne // particolari, colonne sount o palette) - TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); assert(c1BeforeCut - c0BeforeCut + 1 == (int)m_areOldColumnsEmpty.size()); int c; for (c = c0BeforeCut; c <= c1BeforeCut; c++) { @@ -1502,7 +1512,8 @@ int TCellSelection::Range::getColCount() const { return m_c1 - m_c0 + 1; } // TCellSelection //----------------------------------------------------------------------------- -TCellSelection::TCellSelection() : m_timeStretchPopup(0), m_reframePopup(0) { +TCellSelection::TCellSelection() + : m_timeStretchPopup(0), m_reframePopup(0), m_resizePivotRow(-1) { setAlternativeCommandNames(); } @@ -1650,6 +1661,10 @@ void TCellSelection::selectCells(int r0, int c0, int r1, int c1) { m_range.m_r1 = r1; m_range.m_c1 = c1; bool onlyOneRasterLevel = containsOnlyOneRasterLevel(r0, c0, r1, c1); + // set the nearest row + m_resizePivotRow = + (std::abs(r0 - m_resizePivotRow) < std::abs(r1 - m_resizePivotRow)) ? r0 + : r1; CommandManager::instance()->enable(MI_CanvasSize, onlyOneRasterLevel); } @@ -1661,13 +1676,15 @@ void TCellSelection::selectCell(int row, int col) { m_range.m_r1 = row; m_range.m_c1 = col; bool onlyOneRasterLevel = containsOnlyOneRasterLevel(row, col, row, col); + m_resizePivotRow = row; CommandManager::instance()->enable(MI_CanvasSize, onlyOneRasterLevel); } //----------------------------------------------------------------------------- void TCellSelection::selectNone() { - m_range = Range(); + m_range = Range(); + m_resizePivotRow = -1; CommandManager::instance()->enable(MI_CanvasSize, false); } @@ -1861,6 +1878,23 @@ void TCellSelection::pasteCells() { return; } + // pasting cells may change empty column names. So keep old column names for + // undo + std::map emptyColumnNames; + if (Preferences::instance()->isLinkColumnNameWithLevelEnabled()) { + for (int c = c0; c < c0 + cellData->getColCount(); c++) { + TXshColumn *column = xsh->getColumn(c); + if (!column || column->isEmpty()) { + if (!xsh->getStageObject(TStageObjectId::ColumnId(c)) + ->hasSpecifiedName()) + emptyColumnNames[c] = ""; + else + emptyColumnNames[c] = + xsh->getStageObject(TStageObjectId::ColumnId(c))->getName(); + } + } + } + bool isPaste = pasteCellsWithoutUndo(cellData, r0, c0, r1, c1); // Se la selezione corrente e' TCellSelection selezione le celle copiate @@ -1898,9 +1932,9 @@ void TCellSelection::pasteCells() { getLevelSetFromData(cellData, pastedLevels); LevelCmd::addMissingLevelsToCast(pastedLevels); - TUndoManager::manager()->add( - new PasteCellsUndo(r0, c0, r1, c1, oldR0, oldC0, oldR1, oldC1, - areColumnsEmpty, containsSoundColumn)); + TUndoManager::manager()->add(new PasteCellsUndo( + r0, c0, r1, c1, oldR0, oldC0, oldR1, oldC1, areColumnsEmpty, + containsSoundColumn, emptyColumnNames)); TApp::instance()->getCurrentScene()->setDirtyFlag(true); if (containsSoundColumn) TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged(); @@ -2523,8 +2557,20 @@ void TCellSelection::deleteCells(bool withShift) { TUndoManager::manager()->beginBlock(); // remove, then insert empty column for (auto colId : removedColIds) { + // keep column name if specified + std::string columnName = ""; + if (Preferences::instance()->isLinkColumnNameWithLevelEnabled() && + xsh->getStageObject(TStageObjectId::ColumnId(colId)) + ->hasSpecifiedName()) + columnName = + xsh->getStageObject(TStageObjectId::ColumnId(colId))->getName(); + ColumnCmd::deleteColumn(colId, true); ColumnCmd::insertEmptyColumn(colId); + + if (!columnName.empty()) + TStageObjectCmd::rename(TStageObjectId::ColumnId(colId), columnName, + TApp::instance()->getCurrentXsheet()); } } diff --git a/toonz/sources/toonz/cellselection.h b/toonz/sources/toonz/cellselection.h index 55d8f06..2ebb77d 100644 --- a/toonz/sources/toonz/cellselection.h +++ b/toonz/sources/toonz/cellselection.h @@ -33,6 +33,8 @@ public: private: Range m_range; + int m_resizePivotRow; // pivot frame when resizing the selection with + // ctrl+arrow keys public: TCellSelection(); @@ -129,6 +131,7 @@ public: void createBlankDrawing(int row, int col, bool inRange); void createBlankDrawings(); void fillEmptyCell(); + int getResizePivotRow() const { return m_resizePivotRow; } }; #endif // TCELLSELECTION_H diff --git a/toonz/sources/toonz/columncommand.cpp b/toonz/sources/toonz/columncommand.cpp index 8c0b71e..ed65e07 100644 --- a/toonz/sources/toonz/columncommand.cpp +++ b/toonz/sources/toonz/columncommand.cpp @@ -658,6 +658,48 @@ public: int getHistoryType() override { return HistoryType::Xsheet; } }; +//--------------------------------------------------------------------------- + +void doUnifyColumnVisibilityToggles_Recursive(const TXsheet *xsh, + QStringList &modifiedColumnNames, + QList doneList, + QStringList &parentXshStack) { + for (int c = 0; c < xsh->getColumnCount(); c++) { + TXshColumn *column = xsh->getColumn(c); + if (!column || column->isEmpty()) continue; + int colType = column->getColumnType(); + if (colType == TXshColumn::ePaletteType || + colType == TXshColumn::eSoundType || + colType == TXshColumn::eSoundTextType) + continue; + // visibility check + if (column->isPreviewVisible() != column->isCamstandVisible()) { + column->setCamstandVisible(column->isPreviewVisible()); + QString colName = QString::fromStdString( + xsh->getStageObject(TStageObjectId::ColumnId(c))->getName()); + modifiedColumnNames.append(parentXshStack.join(" > ") + colName); + } + + // check subxsheet recursively + TXshCellColumn *cellCol = column->getCellColumn(); + if (!cellCol) continue; + int r0, r1; + column->getRange(r0, r1); + TXshCell cell = cellCol->getCell(r0); + TXshChildLevel *childLevel = cell.m_level->getChildLevel(); + if (childLevel) { + TXsheet *subSheet = childLevel->getXsheet(); + if (!doneList.contains(subSheet)) { + doneList.append(subSheet); + parentXshStack.append(QString::fromStdWString(childLevel->getName())); + doUnifyColumnVisibilityToggles_Recursive(xsh, modifiedColumnNames, + doneList, parentXshStack); + parentXshStack.pop_back(); + } + } + } +} + } // namespace //************************************************************************* @@ -1394,6 +1436,28 @@ bool ColumnCmd::checkExpressionReferences( colIdsToBeDeleted, fxsToBeDeleted, objIdsToBeDuplicated, true); } +//--------------------------------------------------------------------------- +// Check if any column has visibility toggles with different states and the +// "unify visibility toggles" option is enabled +void ColumnCmd::unifyColumnVisibilityToggles() { + TApp *app = TApp::instance(); + ToonzScene *scene = app->getCurrentScene()->getScene(); + QStringList modifiedColumnNames; + QList doneList; + QStringList parentStack; + doUnifyColumnVisibilityToggles_Recursive( + scene->getTopXsheet(), modifiedColumnNames, doneList, parentStack); + if (!modifiedColumnNames.isEmpty()) { + DVGui::warning( + QObject::tr( + "The visibility toggles of following columns are modified \n" + "due to \"Unify Preview and Camstand Visibility Toggles\" " + "preference option : \n %1") + .arg(modifiedColumnNames.join("\n "))); + app->getCurrentScene()->setDirtyFlag(true); + } +} + //============================================================================= namespace { @@ -1482,6 +1546,10 @@ public: column->setPreviewVisible(negate); else column->setPreviewVisible(!column->isPreviewVisible()); + + // sync camstand visibility + if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + column->setCamstandVisible(column->isPreviewVisible()); } if (cmd & (CMD_ENABLE_CAMSTAND | CMD_DISABLE_CAMSTAND | CMD_TOGGLE_CAMSTAND)) { diff --git a/toonz/sources/toonz/columncommand.h b/toonz/sources/toonz/columncommand.h index a0754c5..1526067 100644 --- a/toonz/sources/toonz/columncommand.h +++ b/toonz/sources/toonz/columncommand.h @@ -54,6 +54,10 @@ bool checkExpressionReferences(const std::set &indices, // checkInvert is always true for collapsing in stage schematic bool checkExpressionReferences(const QList &objects); +// Check if any column has visibility toggles with different states and the +// "unify visibility toggles" option is enabled +void unifyColumnVisibilityToggles(); + } // namespace ColumnCmd #endif diff --git a/toonz/sources/toonz/icons/dark/actions/16/gear_check.svg b/toonz/sources/toonz/icons/dark/actions/16/gear_check.svg new file mode 100644 index 0000000..885734b --- /dev/null +++ b/toonz/sources/toonz/icons/dark/actions/16/gear_check.svg @@ -0,0 +1,56 @@ + + + + + + + + + diff --git a/toonz/sources/toonz/iocommand.cpp b/toonz/sources/toonz/iocommand.cpp index 14cfb28..d6c8744 100644 --- a/toonz/sources/toonz/iocommand.cpp +++ b/toonz/sources/toonz/iocommand.cpp @@ -22,6 +22,7 @@ #include "xdtsio.h" #include "expressionreferencemanager.h" #include "levelcommand.h" +#include "columncommand.h" // TnzTools includes #include "tools/toolhandle.h" @@ -1200,7 +1201,6 @@ inline TPaletteP dirtyWhite(const TPaletteP &plt) { return out; } -//--------------------------------------------------------------------------- } // namespace //--------------------------------------------------------------------------- @@ -2088,6 +2088,11 @@ bool IoCmd::loadScene(const TFilePath &path, bool updateRecentFile, } } + // Check if any column has visibility toggles with different states and the + // "unify visibility toggles" option is enabled + if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + ColumnCmd::unifyColumnVisibilityToggles(); + // caching raster levels int cacheRasterBehavior = Preferences::instance()->getRasterLevelCachingBehavior(); diff --git a/toonz/sources/toonz/layerheaderpanel.cpp b/toonz/sources/toonz/layerheaderpanel.cpp index d7b922c..b188fb6 100644 --- a/toonz/sources/toonz/layerheaderpanel.cpp +++ b/toonz/sources/toonz/layerheaderpanel.cpp @@ -66,7 +66,8 @@ void LayerHeaderPanel::paintEvent(QPaintEvent *event) { : m_viewer->getLayerHeaderLockImage()); drawIcon(p, PredefinedRect::PANEL_EYE, boost::none, preview); - drawIcon(p, PredefinedRect::PANEL_PREVIEW_LAYER, boost::none, camstand); + if (!Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + drawIcon(p, PredefinedRect::PANEL_PREVIEW_LAYER, boost::none, camstand); drawIcon(p, PredefinedRect::PANEL_LOCK, boost::none, lock); } diff --git a/toonz/sources/toonz/ocaio.cpp b/toonz/sources/toonz/ocaio.cpp index e3692cd..51e5dc7 100644 --- a/toonz/sources/toonz/ocaio.cpp +++ b/toonz/sources/toonz/ocaio.cpp @@ -479,12 +479,14 @@ void ExportOCACommand::execute() { QDir saveDir(ocafolder); if (!saveFile.open(QIODevice::WriteOnly)) { - qWarning("Couldn't open save file."); + progressDialog->close(); + DVGui::error(QObject::tr("Unable to open OCA file for saving.")); return; } if (!saveDir.exists()) { - if (!saveDir.mkdir(".")) { - qWarning("Couldn't create folder."); + if (!saveDir.mkpath(".")) { + progressDialog->close(); + DVGui::error(QObject::tr("Unable to create folder for saving layers.")); return; } } @@ -494,6 +496,7 @@ void ExportOCACommand::execute() { ocaData.build(scene, xsheet, QString::fromStdString(fp.getName()), ocafolder, frameOffset, exrImageFmt, !rasterVecs); if (ocaData.isEmpty()) { + progressDialog->close(); DVGui::error(QObject::tr("No columns can be exported.")); return; } diff --git a/toonz/sources/toonz/pane.cpp b/toonz/sources/toonz/pane.cpp index 2f2662f..43e8f5b 100644 --- a/toonz/sources/toonz/pane.cpp +++ b/toonz/sources/toonz/pane.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include extern TEnv::StringVar EnvSafeAreaName; @@ -123,7 +124,8 @@ void TPanel::enterEvent(QEvent *event) { if (w) { // grab the focus, unless a line-edit is focused currently QWidget *focusWidget = qApp->focusWidget(); - if (focusWidget && dynamic_cast(focusWidget)) { + if (focusWidget && (dynamic_cast(focusWidget) || + dynamic_cast(focusWidget))) { event->accept(); return; } diff --git a/toonz/sources/toonz/penciltestpopup.cpp b/toonz/sources/toonz/penciltestpopup.cpp index 84e6a94..a96098e 100644 --- a/toonz/sources/toonz/penciltestpopup.cpp +++ b/toonz/sources/toonz/penciltestpopup.cpp @@ -124,6 +124,7 @@ TEnv::IntVar CamCapDoCalibration("CamCapDoCalibration", 0); TEnv::RectVar CamCapSubCameraRect("CamCapSubCameraRect", TRect()); TEnv::IntVar CamCapDoAutoDpi("CamCapDoAutoDpi", 1); TEnv::DoubleVar CamCapCustomDpi("CamCapDpiForNewLevel", 120.0); +TEnv::StringVar CamCapFileType("CamCapFileType", "jpg"); namespace { @@ -433,6 +434,38 @@ protected: } }; +// https://stackoverflow.com/a/50848100/6622587 +cv::Mat QImageToMat(const QImage& image) { + cv::Mat out; + switch (image.format()) { + case QImage::Format_Invalid: { + cv::Mat empty; + empty.copyTo(out); + break; + } + case QImage::Format_RGB32: { + cv::Mat view(image.height(), image.width(), CV_8UC4, + (void*)image.constBits(), image.bytesPerLine()); + view.copyTo(out); + break; + } + case QImage::Format_RGB888: { + cv::Mat view(image.height(), image.width(), CV_8UC3, + (void*)image.constBits(), image.bytesPerLine()); + cv::cvtColor(view, out, cv::COLOR_RGB2BGR); + break; + } + default: { + QImage conv = image.convertToFormat(QImage::Format_ARGB32); + cv::Mat view(conv.height(), conv.width(), CV_8UC4, (void*)conv.constBits(), + conv.bytesPerLine()); + view.copyTo(out); + break; + } + } + return out; +} + } // namespace //============================================================================= @@ -1556,8 +1589,9 @@ PencilTestPopup::PencilTestPopup() m_saveOnCaptureCB = new QCheckBox(tr("Save images as they are captured"), this); - QGroupBox* imageFrame = new QGroupBox(tr("Image adjust"), this); - m_colorTypeCombo = new QComboBox(this); + QGroupBox* imageFrame = new QGroupBox(tr("Image adjust"), this); + m_colorTypeCombo = new QComboBox(this); + m_saveImgAdjustDefaultButton = new QPushButton(this); m_camCapLevelControl = new CameraCaptureLevelControl(this); m_upsideDownCB = new QCheckBox(tr("Upside down"), this); @@ -1610,7 +1644,7 @@ PencilTestPopup::PencilTestPopup() m_resolutionCombo->setMaximumWidth(fontMetrics().width("0000 x 0000") + 25); m_fileTypeCombo->addItems({"jpg", "png", "tga", "tif"}); - m_fileTypeCombo->setCurrentIndex(0); + m_fileTypeCombo->setCurrentText(QString::fromStdString(CamCapFileType)); fileFrame->setObjectName("CleanupSettingsFrame"); m_frameNumberEdit->setObjectName("LargeSizedText"); @@ -1627,6 +1661,11 @@ PencilTestPopup::PencilTestPopup() m_colorTypeCombo->addItems( {tr("Color"), tr("Grayscale"), tr("Black & White")}); m_colorTypeCombo->setCurrentIndex(0); + m_saveImgAdjustDefaultButton->setFixedSize(24, 24); + m_saveImgAdjustDefaultButton->setIconSize(QSize(16, 16)); + m_saveImgAdjustDefaultButton->setIcon(createQIcon("gear_check")); + m_saveImgAdjustDefaultButton->setToolTip( + tr("Save Current Image Adjust Parameters As Default")); m_upsideDownCB->setChecked(false); m_bgReductionFld->setRange(0, 100); @@ -1824,6 +1863,8 @@ PencilTestPopup::PencilTestPopup() imageLay->addWidget(new QLabel(tr("Color type:"), this), 0, 0, Qt::AlignRight); imageLay->addWidget(m_colorTypeCombo, 0, 1); + imageLay->addWidget(m_saveImgAdjustDefaultButton, 0, 2, + Qt::AlignRight); imageLay->addWidget(m_camCapLevelControl, 1, 0, 1, 3); @@ -1918,6 +1959,8 @@ PencilTestPopup::PencilTestPopup() SLOT(onPreviousName())); ret = ret && connect(m_colorTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onColorTypeComboChanged(int))); + ret = ret && connect(m_saveImgAdjustDefaultButton, SIGNAL(pressed()), this, + SLOT(saveImageAdjustDefault())); ret = ret && connect(m_captureWhiteBGButton, SIGNAL(pressed()), this, SLOT(onCaptureWhiteBGButtonPressed())); ret = ret && connect(m_onionSkinGBox, SIGNAL(toggled(bool)), this, @@ -1942,8 +1985,12 @@ PencilTestPopup::PencilTestPopup() SLOT(openSaveInFolderPopup())); ret = ret && connect(m_saveInFileFld, SIGNAL(pathChanged()), this, SLOT(onSaveInPathEdited())); - ret = ret && connect(m_fileTypeCombo, SIGNAL(activated(int)), this, - SLOT(refreshFrameInfo())); + ret = ret && + connect(m_fileTypeCombo, QOverload::of(&QComboBox::activated), + [&](int index) { + CamCapFileType = m_fileTypeCombo->currentText().toStdString(); + refreshFrameInfo(); + }); ret = ret && connect(m_frameNumberEdit, SIGNAL(editingFinished()), this, SLOT(refreshFrameInfo())); @@ -2040,6 +2087,9 @@ PencilTestPopup::PencilTestPopup() m_videoWidget->setImage(dummyImg); m_subcameraButton->setChecked(true); } + + // try loading the default parameter + loadImageAdjustDefault(); } } @@ -3466,6 +3516,13 @@ void PencilTestPopup::onSaveInPathEdited() { //----------------------------------------------------------------------------- +void PencilTestPopup::onFileTypeChanged() { + CamCapFileType = m_fileTypeCombo->currentText().toStdString(); + refreshFrameInfo(); +} + +//----------------------------------------------------------------------------- + void PencilTestPopup::onSceneSwitched() { m_saveInFolderPopup->updateParentFolder(); m_saveInFileFld->setPath(m_saveInFolderPopup->getParentPath()); @@ -3616,14 +3673,33 @@ void PencilTestPopup::resetCalibSettingsFromFile() { //----------------------------------------------------------------------------- -QString PencilTestPopup::getCurrentCalibFilePath() { +QString PencilTestPopup::getCameraConfigurationPath(const QString& folderName, + const QString& ext) { QString cameraName = m_cameraListCombo->currentText(); if (cameraName.isEmpty()) return QString(); QString resolution = m_resolutionCombo->currentText(); QString hostName = QHostInfo::localHostName(); - TFilePath folderPath = ToonzFolder::getLibraryFolder() + "camera calibration"; - return folderPath.getQString() + "\\" + hostName + "_" + cameraName + "_" + - resolution + ".xml"; + TFilePath folderPath = ToonzFolder::getLibraryFolder(); + return folderPath.getQString() + "\\" + folderName + "\\" + hostName + "_" + + cameraName + "_" + resolution + "." + ext; +} + +//----------------------------------------------------------------------------- + +QString PencilTestPopup::getCurrentCalibFilePath() { + return getCameraConfigurationPath("camera calibration", "xml"); +} + +//----------------------------------------------------------------------------- + +QString PencilTestPopup::getImageAdjustSettingsPath() { + return getCameraConfigurationPath("camera image adjust", "ini"); +} + +//----------------------------------------------------------------------------- + +QString PencilTestPopup::getImageAdjustBgImgPath() { + return getCameraConfigurationPath("camera image adjust", "jpg"); } //----------------------------------------------------------------------------- @@ -3789,6 +3865,80 @@ void PencilTestPopup::onPreferenceChanged(const QString& prefName) { } //----------------------------------------------------------------------------- +// called in ctor +void PencilTestPopup::loadImageAdjustDefault() { + // find the configuration file + QString settingsPath = getImageAdjustSettingsPath(); + if (!TFileStatus(TFilePath(settingsPath)).doesExist()) return; + + QSettings imgAdjSettings(settingsPath, QSettings::IniFormat); + int colorType = imgAdjSettings.value("ColorType", 0).toInt(); + int black = imgAdjSettings.value("BlackLevel", 0).toInt(); + int white = imgAdjSettings.value("WhiteLevel", 255).toInt(); + double gamma = imgAdjSettings.value("Gamma", 1.0).toDouble(); + int threshold = imgAdjSettings.value("Threshold", 128).toInt(); + bool upsideDown = imgAdjSettings.value("UpsideDown", false).toBool(); + int bgReduction = imgAdjSettings.value("BgReduction", 0).toInt(); + + m_colorTypeCombo->setCurrentIndex(colorType); + m_camCapLevelControl->setValues(black, white, threshold, gamma, + colorType != 2); + m_upsideDownCB->setChecked(upsideDown); + m_bgReductionFld->setValue(bgReduction); + + QString bgPath = getImageAdjustBgImgPath(); + if (!TFileStatus(TFilePath(bgPath)).doesExist()) { + if (bgReduction > 0) + warning( + tr("BG Reduction is set but the White BG image is missing. Please " + "capture the White BG again.")); + + m_whiteBGImg = cv::Mat(); + m_bgReductionFld->setDisabled(true); + return; + } + + QImage bgImg(bgPath); + if (bgImg.isNull()) { + m_whiteBGImg = cv::Mat(); + m_bgReductionFld->setDisabled(true); + return; + } + cv::Mat tmpMat = QImageToMat(bgImg); + cv::cvtColor(tmpMat, m_whiteBGImg, cv::COLOR_RGBA2RGB); + m_bgReductionFld->setEnabled(true); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::saveImageAdjustDefault() { + QString question = + tr("Do you want to save the current parameters as the default values?"); + int ret = DVGui::MsgBox(question, QObject::tr("Save"), QObject::tr("Cancel")); + if (ret == 0 || ret == 2) return; + + QString settingsPath = getImageAdjustSettingsPath(); + QSettings imgAdjSettings(settingsPath, QSettings::IniFormat); + + imgAdjSettings.setValue("ColorType", m_colorTypeCombo->currentIndex()); + int black, white, threshold; + double gamma; + m_camCapLevelControl->getValues(black, white, threshold, gamma); + imgAdjSettings.setValue("BlackLevel", black); + imgAdjSettings.setValue("WhiteLevel", white); + imgAdjSettings.setValue("Gamma", gamma); + imgAdjSettings.setValue("Threshold", threshold); + imgAdjSettings.setValue("UpsideDown", m_upsideDownCB->isChecked()); + imgAdjSettings.setValue("BgReduction", m_bgReductionFld->getValue()); + + if (!m_whiteBGImg.empty()) { + QImage qimg(m_whiteBGImg.data, m_whiteBGImg.cols, m_whiteBGImg.rows, + QImage::Format_RGB888); + qimg.save(getImageAdjustBgImgPath()); + } +} + +//----------------------------------------------------------------------------- OpenPopupCommandHandler openPencilTestPopup(MI_PencilTest); diff --git a/toonz/sources/toonz/penciltestpopup.h b/toonz/sources/toonz/penciltestpopup.h index 60fe140..397cb97 100644 --- a/toonz/sources/toonz/penciltestpopup.h +++ b/toonz/sources/toonz/penciltestpopup.h @@ -271,7 +271,7 @@ class PencilTestPopup : public DVGui::Dialog { QCheckBox *m_upsideDownCB, *m_saveOnCaptureCB; QGroupBox *m_onionSkinGBox, *m_timerGBox; QPushButton *m_fileFormatOptionButton, *m_captureWhiteBGButton, - *m_captureButton, *m_loadImageButton; + *m_captureButton, *m_loadImageButton, *m_saveImgAdjustDefaultButton; DVGui::FileField* m_saveInFileFld; FrameNumberLineEdit* m_frameNumberEdit; DVGui::IntField *m_bgReductionFld, *m_onionOpacityFld, *m_timerIntervalFld; @@ -341,8 +341,13 @@ class PencilTestPopup : public DVGui::Dialog { QMenu* createOptionsMenu(); int translateIndex(int camIndex); + void loadImageAdjustDefault(); QString getCurrentCalibFilePath(); + QString getImageAdjustSettingsPath(); + QString getImageAdjustBgImgPath(); + QString getCameraConfigurationPath(const QString& folderName, + const QString& ext); QWidget* createDpiMenuWidget(); @@ -381,6 +386,7 @@ protected slots: void refreshFrameInfo(); void onSaveInPathEdited(); + void onFileTypeChanged(); void onSceneSwitched(); void onSubCameraToggled(bool); @@ -398,6 +404,8 @@ protected slots: void onCalibReadme(); void onPreferenceChanged(const QString&); + void saveImageAdjustDefault(); + public slots: void openSaveInFolderPopup(); }; diff --git a/toonz/sources/toonz/preferencespopup.cpp b/toonz/sources/toonz/preferencespopup.cpp index e0199df..9e8ef56 100644 --- a/toonz/sources/toonz/preferencespopup.cpp +++ b/toonz/sources/toonz/preferencespopup.cpp @@ -9,6 +9,7 @@ #include "tapp.h" #include "cleanupsettingsmodel.h" #include "formatsettingspopups.h" +#include "columncommand.h" // TnzQt includes #include "toonzqt/tabbar.h" @@ -679,6 +680,18 @@ void PreferencesPopup::onShowXSheetToolbarClicked() { //----------------------------------------------------------------------------- +void PreferencesPopup::onUnifyColumnVisibilityTogglesChanged() { + // Check if any column has visibility toggles with different states and the + // "unify visibility toggles" option is enabled + if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + ColumnCmd::unifyColumnVisibilityToggles(); + + TApp::instance()->getCurrentScene()->notifyPreferenceChanged( + "unifyColumnVisibilityToggles"); +} + +//----------------------------------------------------------------------------- + void PreferencesPopup::onModifyExpressionOnMovingReferencesChanged() { TApp::instance()->getCurrentScene()->notifyPreferenceChanged( "modifyExpressionOnMovingReferences"); @@ -1279,6 +1292,8 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) { {expandFunctionHeader, tr("Expand Function Editor Header to Match Xsheet Toolbar Height*")}, {showColumnNumbers, tr("Show Column Numbers in Column Headers")}, + {unifyColumnVisibilityToggles, + tr("Unify Preview and Camstand Visibility Toggles")}, {parentColorsInXsheetColumn, tr("Show Column Parent's Color in the Xsheet")}, {highlightLineEverySecond, tr("Highlight Line Every Second")}, @@ -1291,6 +1306,7 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) { {levelNameDisplayType, tr("Level Name Display:")}, {showFrameNumberWithLetters, tr("Show \"ABC\" Appendix to the Frame Number in Xsheet Cell")}, + {linkColumnNameWithLevel, tr("Link Column Name with Level")}, // Animation {keyframeType, tr("Default Interpolation:")}, @@ -1432,7 +1448,9 @@ QList PreferencesPopup::getComboItemList( {tr("Display on Column Header"), Preferences::ShowLevelNameOnColumnHeader}}}, {DragCellsBehaviour, - {{tr("Cells Only"), 0}, {tr("Cells and Column Data"), 1}}}, + {{tr("Cells Only"), 0}, + {tr("Cells and Column Data"), 1}, + {tr("Disable Dragging Cells"), 2}}}, {deleteCommandBehavior, {{tr("Clear Cell / Frame"), 0}, {tr("Remove and Shift Cells / Frames Up"), 1}}}, @@ -1998,6 +2016,7 @@ QWidget* PreferencesPopup::createXsheetPage() { insertUI(xsheetLayoutPreference, lay, getComboItemList(xsheetLayoutPreference)); insertUI(levelNameDisplayType, lay, getComboItemList(levelNameDisplayType)); + insertUI(linkColumnNameWithLevel, lay); insertUI(xsheetStep, lay); insertUI(xsheetAutopanEnabled, lay); insertUI(DragCellsBehaviour, lay, getComboItemList(DragCellsBehaviour)); @@ -2013,6 +2032,7 @@ QWidget* PreferencesPopup::createXsheetPage() { QGridLayout* xshToolbarLay = insertGroupBoxUI(showXSheetToolbar, lay); { insertUI(expandFunctionHeader, xshToolbarLay); } insertUI(showColumnNumbers, lay); + insertUI(unifyColumnVisibilityToggles, lay); insertUI(parentColorsInXsheetColumn, lay); insertUI(highlightLineEverySecond, lay); insertUI(syncLevelRenumberWithXsheet, lay); @@ -2028,7 +2048,19 @@ QWidget* PreferencesPopup::createXsheetPage() { &PreferencesPopup::onShowKeyframesOnCellAreaChanged); m_onEditedFuncMap.insert(showXsheetCameraColumn, &PreferencesPopup::onShowKeyframesOnCellAreaChanged); - + m_onEditedFuncMap.insert( + unifyColumnVisibilityToggles, + &PreferencesPopup::onUnifyColumnVisibilityTogglesChanged); + + QCheckBox* linkColumnNameWithLevelCheck = + getUI(linkColumnNameWithLevel); + linkColumnNameWithLevelCheck->setToolTip( + tr("This option will do the following:\n" + "- When setting a cell in the empty column, level name will be copied " + "to the column name\n" + "- Typing the cell without level name in the empty column will try to " + "use a level with the same name as the column\n" + "The behavior may be changed in the future development.")); return widget; } diff --git a/toonz/sources/toonz/preferencespopup.h b/toonz/sources/toonz/preferencespopup.h index c1e1e1e..de08a94 100644 --- a/toonz/sources/toonz/preferencespopup.h +++ b/toonz/sources/toonz/preferencespopup.h @@ -139,6 +139,7 @@ private: // Xsheet void onShowKeyframesOnCellAreaChanged(); void onShowXSheetToolbarClicked(); + void onUnifyColumnVisibilityTogglesChanged(); // Animation void onModifyExpressionOnMovingReferencesChanged(); // Preview diff --git a/toonz/sources/toonz/toonz.qrc b/toonz/sources/toonz/toonz.qrc index dad7582..5070c00 100644 --- a/toonz/sources/toonz/toonz.qrc +++ b/toonz/sources/toonz/toonz.qrc @@ -76,7 +76,8 @@ icons/dark/actions/16/save.svg icons/dark/actions/16/saveas.svg icons/dark/actions/16/saveall.svg - icons/dark/actions/16/gear.svg + icons/dark/actions/16/gear.svg + icons/dark/actions/16/gear_check.svg icons/dark/actions/16/settings_reset.svg icons/dark/actions/16/clear.svg icons/dark/actions/16/undo.svg diff --git a/toonz/sources/toonz/tpanels.cpp b/toonz/sources/toonz/tpanels.cpp index 00889eb..bf8e406 100644 --- a/toonz/sources/toonz/tpanels.cpp +++ b/toonz/sources/toonz/tpanels.cpp @@ -266,6 +266,13 @@ void SchematicScenePanel::onColumnPaste(const QList &columns) { //----------------------------------------------------------------------------- +void SchematicScenePanel::onPreferenceChanged(const QString &prefName) { + if (prefName == "unifyColumnVisibilityToggles") + m_schematicViewer->updateSchematic(); +} + +//----------------------------------------------------------------------------- + void SchematicScenePanel::showEvent(QShowEvent *e) { if (m_schematicViewer->isStageSchematicViewed()) setWindowTitle(QObject::tr("Stage Schematic")); @@ -299,6 +306,8 @@ void SchematicScenePanel::showEvent(QShowEvent *e) { SLOT(updateSchematic())); connect(app->getCurrentScene(), SIGNAL(sceneSwitched()), m_schematicViewer, SLOT(onSceneSwitched())); + connect(app->getCurrentScene(), SIGNAL(preferenceChanged(const QString &)), + this, SLOT(onPreferenceChanged(const QString &))); connect(m_schematicViewer, SIGNAL(columnPasted(const QList &)), this, SLOT(onColumnPaste(const QList &))); m_schematicViewer->updateSchematic(); @@ -330,6 +339,8 @@ void SchematicScenePanel::hideEvent(QHideEvent *e) { m_schematicViewer, SLOT(updateSchematic())); disconnect(app->getCurrentScene(), SIGNAL(sceneSwitched()), m_schematicViewer, SLOT(onSceneSwitched())); + disconnect(app->getCurrentScene(), SIGNAL(preferenceChanged(const QString &)), + this, SLOT(onPreferenceChanged(const QString &))); disconnect(m_schematicViewer, SIGNAL(columnPasted(const QList &)), this, SLOT(onColumnPaste(const QList &))); diff --git a/toonz/sources/toonz/tpanels.h b/toonz/sources/toonz/tpanels.h index c06bc53..1102944 100644 --- a/toonz/sources/toonz/tpanels.h +++ b/toonz/sources/toonz/tpanels.h @@ -193,6 +193,7 @@ protected slots: void onDeleteFxs(const FxSelection *); void onDeleteStageObjects(const StageObjectSelection *); void onColumnPaste(const QList &); + void onPreferenceChanged(const QString &); }; //========================================================= diff --git a/toonz/sources/toonz/xshcellviewer.cpp b/toonz/sources/toonz/xshcellviewer.cpp index bf27a8b..2666bd5 100644 --- a/toonz/sources/toonz/xshcellviewer.cpp +++ b/toonz/sources/toonz/xshcellviewer.cpp @@ -76,7 +76,8 @@ namespace { -const bool checkContainsSingleLevel(TXshColumn *column) { +const bool checkContainsSingleLevel(TXshColumn *column, + const std::string &columnName) { TXshLevel *level = nullptr; TXshCellColumn *cellColumn = column->getCellColumn(); if (cellColumn) { @@ -91,7 +92,9 @@ const bool checkContainsSingleLevel(TXshColumn *column) { else if (lvl != level) return false; } - return level != nullptr; + // column name should be unspecified or same as the content level + return level != nullptr && + (columnName.empty() || level->getName() == to_wstring(columnName)); } return false; } @@ -856,6 +859,26 @@ void RenameCellField::renameCell() { // previous frames // (when editing not empty column) if (xsheet->isColumnEmpty(c)) { + // find a level with name same as the column (if the preferences option + // is set to do so) + if (Preferences::instance()->isLinkColumnNameWithLevelEnabled() && + xsheet->getStageObject(TStageObjectId::ColumnId(c)) + ->hasSpecifiedName()) { + std::string columnName = + xsheet->getStageObject(TStageObjectId::ColumnId(c))->getName(); + TLevelSet *levelSet = scene->getLevelSet(); + TXshLevel *xl = levelSet->getLevel(to_wstring(columnName)); + TXshSimpleLevel *sl = (xl) ? xl->getSimpleLevel() : nullptr; + if (sl && + (!sl->isEmpty() || sl->getFirstFid() != TFrameId::NO_FRAME)) { + sl->formatFId(fid, tmplFId); + cells.append(TXshCell(xl, fid)); + changed = true; + hasFrameZero = (fid.getNumber() == 0 && xl->getSimpleLevel() && + xl->getSimpleLevel()->isFid(fid)); + continue; + } + } cells.append(TXshCell()); continue; } @@ -1270,10 +1293,16 @@ void CellArea::drawCells(QPainter &p, const QRect toBeUpdated) { isPaletteColumn = column->getPaletteColumn() != 0; isSoundTextColumn = column->getSoundTextColumn() != 0; if (Preferences::instance()->getLevelNameDisplayType() == - Preferences::ShowLevelNameOnColumnHeader) + Preferences::ShowLevelNameOnColumnHeader) { + std::string columnName = ""; + if (col >= 0 && xsh->getStageObject(TStageObjectId::ColumnId(col)) + ->hasSpecifiedName()) + columnName = + xsh->getStageObject(TStageObjectId::ColumnId(col))->getName(); showLevelName = (isSoundColumn || isPaletteColumn || isSoundTextColumn || - !checkContainsSingleLevel(column)); + !checkContainsSingleLevel(column, columnName)); + } } // check if the column is reference bool isReference = true; @@ -1413,6 +1442,9 @@ void CellArea::drawExtenderHandles(QPainter &p) { TCellSelection *cellSelection = m_viewer->getCellSelection(); if (cellSelection->isEmpty() || m_viewer->areSoundCellsSelected()) return; + // if the drag move is disabled, the extender handles won't appear + if (Preferences::instance()->getDragCellsBehaviour() == 2) return; + int selRow0, selCol0, selRow1, selCol1; cellSelection->getSelectedCells(selRow0, selCol0, selRow1, selCol1); @@ -3332,7 +3364,7 @@ void CellArea::mousePressEvent(QMouseEvent *event) { if (TCellKeyframeSelection *cellKeyframeSelection = dynamic_cast(selection)) setDragTool(XsheetGUI::DragTool::makeCellKeyframeMoverTool(m_viewer)); - else + else if (Preferences::instance()->getDragCellsBehaviour() != 2) setDragTool(XsheetGUI::DragTool::makeLevelMoverTool(m_viewer)); } else { m_viewer->getKeyframeSelection()->selectNone(); diff --git a/toonz/sources/toonz/xshcolumnviewer.cpp b/toonz/sources/toonz/xshcolumnviewer.cpp index d9e38f3..c3b0416 100644 --- a/toonz/sources/toonz/xshcolumnviewer.cpp +++ b/toonz/sources/toonz/xshcolumnviewer.cpp @@ -49,6 +49,7 @@ #include "toonz/tfxhandle.h" #include "toonz/tcamera.h" #include "toonz/tcolumnhandle.h" +#include "toonz/levelset.h" // TnzCore includes #include "tconvert.h" @@ -707,12 +708,18 @@ void RenameColumnField::renameColumn() { : TStageObjectId::CameraId(cameraIndex); TXshColumn *column = m_xsheetHandle->getXsheet()->getColumn(columnId.getIndex()); + if (!column && m_col >= 0) { + m_xsheetHandle->getXsheet()->insertColumn(m_col); + column = m_xsheetHandle->getXsheet()->getColumn(columnId.getIndex()); + } + TXshZeraryFxColumn *zColumn = dynamic_cast(column); if (zColumn) TFxCommand::renameFx(zColumn->getZeraryColumnFx(), ::to_wstring(newName), m_xsheetHandle); else TStageObjectCmd::rename(columnId, newName, m_xsheetHandle); + m_xsheetHandle->notifyXsheetChanged(); m_col = -1; setText(""); @@ -745,7 +752,7 @@ const bool ColumnArea::isControlPressed() { return isCtrlPressed; } //----------------------------------------------------------------------------- ColumnArea::DrawHeader::DrawHeader(ColumnArea *nArea, QPainter &nP, int nCol) - : area(nArea), p(nP), col(nCol) { + : area(nArea), p(nP), col(nCol), reservedLevel(nullptr) { m_viewer = area->m_viewer; o = m_viewer->orientation(); app = TApp::instance(); @@ -753,6 +760,18 @@ ColumnArea::DrawHeader::DrawHeader(ColumnArea *nArea, QPainter &nP, int nCol) column = xsh->getColumn(col); isEmpty = col >= 0 ? xsh->isColumnEmpty(col) : false; + if (isEmpty && Preferences::instance()->isLinkColumnNameWithLevelEnabled() && + m_viewer->getXsheet() + ->getStageObject(TStageObjectId::ColumnId(col)) + ->hasSpecifiedName()) { + std::string columnName = m_viewer->getXsheet() + ->getStageObject(TStageObjectId::ColumnId(col)) + ->getName(); + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + TLevelSet *levelSet = scene->getLevelSet(); + reservedLevel = levelSet->getLevel(to_wstring(columnName)); + } + TStageObjectId currentColumnId = app->getCurrentObject()->getObjectId(); // check if the column is current @@ -816,7 +835,11 @@ void ColumnArea::DrawHeader::levelColors(QColor &columnColor, if (column->isRendered() || column->getMeshColumn()) usage = Normal; } - if (usage == Reference) { + if (reservedLevel) { + int ltype; + m_viewer->getCellTypeAndColors(ltype, columnColor, dragColor, + TXshCell(reservedLevel, TFrameId())); + } else if (usage == Reference) { columnColor = m_viewer->getReferenceColumnColor(); dragColor = m_viewer->getReferenceColumnBorderColor(); } else @@ -859,15 +882,17 @@ void ColumnArea::DrawHeader::drawBaseFill(const QColor &columnColor, // Fill base color, in timeline view adjust it right upto thumbnail so column // head color doesn't show under icon switches. - if (isEmpty) + if (isEmpty && !reservedLevel) p.fillRect(o->isVerticalTimeline() ? rect : rect.adjusted(80, 0, 0, 0), m_viewer->getEmptyColumnHeadColor()); else if (col < 0) p.fillRect(o->isVerticalTimeline() ? rect : rect.adjusted(80, 0, 0, 0), columnColor); else { + QBrush brush(columnColor, + (reservedLevel) ? Qt::DiagCrossPattern : Qt::SolidPattern); p.fillRect(o->isVerticalTimeline() ? rect : rect.adjusted(80, 0, 0, 0), - columnColor); + brush); if (o->flag(PredefinedFlag::DRAG_LAYER_VISIBLE)) { // column handle @@ -976,6 +1001,43 @@ void ColumnArea::DrawHeader::drawPreviewToggle(int opacity) const { p.drawImage(tableViewImgRect, icon); } +// shows united visibility toggle, which has the same state as the camstand +// toggle (preview toggle should synchonize with the camstand toggle) +void ColumnArea::DrawHeader::drawUnifiedViewToggle(int opacity) const { + if (isEmpty || !o->flag(PredefinedFlag::PREVIEW_LAYER_AREA_VISIBLE)) return; + if (col < 0 && o->isVerticalTimeline()) + return; // no camstand toggle in the camera column + // camstand visible toggle + QColor bgColor; + QImage icon; + int buttonType = !column->isCamstandVisible() ? PREVIEW_OFF_XSHBUTTON + : opacity < 255 ? UNIFIED_TRANSP_XSHBUTTON + : PREVIEW_ON_XSHBUTTON; + m_viewer->getButton(buttonType, bgColor, icon, !o->isVerticalTimeline()); + + QRect unifiedViewRect = + o->rect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA).translated(orig); + QRect unifiedViewImgRect = + o->rect(PredefinedRect::UNIFIEDVIEW_LAYER).translated(orig); + + if (o->isVerticalTimeline()) + p.setPen(m_viewer->getColumnIconLineColor()); // border color + else + p.setPen(m_viewer->getTimelineIconLineColor()); // border color + + if (col < 0 || column->getPaletteColumn() || column->getSoundTextColumn()) { + if (o->flag(PredefinedFlag::PREVIEW_LAYER_AREA_BORDER)) + p.drawRect(unifiedViewRect); + return; + } + + p.fillRect(unifiedViewRect, bgColor); + if (o->flag(PredefinedFlag::PREVIEW_LAYER_AREA_BORDER)) + p.drawRect(unifiedViewRect); + + p.drawImage(unifiedViewImgRect, icon); +} + void ColumnArea::DrawHeader::drawLock() const { if (isEmpty || !o->flag(PredefinedFlag::LOCK_AREA_VISIBLE)) return; QColor bgColor; @@ -1582,65 +1644,19 @@ void ColumnArea::drawFoldedColumnHead(QPainter &p, int col) { } void ColumnArea::drawLevelColumnHead(QPainter &p, int col) { - TColumnSelection *selection = m_viewer->getColumnSelection(); - const Orientation *o = m_viewer->orientation(); - - // Preparing painter - QString fontName = Preferences::instance()->getInterfaceFont(); - if (fontName == "") { -#ifdef _WIN32 - fontName = "Arial"; -#else - fontName = "Helvetica"; -#endif - } - static QFont font(fontName, -1, QFont::Normal); - font.setPixelSize(XSHEET_FONT_PX_SIZE); - - p.setFont(font); - p.setRenderHint(QPainter::SmoothPixmapTransform, true); - - // Retrieve reference coordinates - int currentColumnIndex = m_viewer->getCurrentColumn(); - int layerAxis = m_viewer->columnToLayerAxis(col); - - QPoint orig = m_viewer->positionToXY(CellPosition(0, col)); - QRect rect = o->rect(PredefinedRect::LAYER_HEADER).translated(orig); - - TApp *app = TApp::instance(); - TXsheet *xsh = m_viewer->getXsheet(); - - TStageObjectId columnId = m_viewer->getObjectId(col); - TStageObjectId currentColumnId = app->getCurrentObject()->getObjectId(); - TStageObjectId parentId = xsh->getStageObjectParent(columnId); - - // Retrieve column properties - // Check if the column is empty - bool isEmpty = col >= 0 && xsh->isColumnEmpty(col); - TXshColumn *column = col >= 0 ? xsh->getColumn(col) : 0; - - bool isEditingSpline = app->getCurrentObject()->isSpline(); - - // check if the column is current - bool isCurrent = false; - if (currentColumnId == - TStageObjectId::CameraId(xsh->getCameraColumnIndex())) // CAMERA - isCurrent = col == -1; - else - isCurrent = m_viewer->getCurrentColumn() == col; - - bool isSelected = - m_viewer->getColumnSelection()->isColumnSelected(col) && !isEditingSpline; - // bool isCameraSelected = col == -1 && isCurrent && !isEditingSpline; - + TXshColumn *column = col >= 0 ? m_viewer->getXsheet()->getColumn(col) : 0; // Draw column DrawHeader drawHeader(this, p, col); drawHeader.prepare(); QColor columnColor, dragColor; drawHeader.levelColors(columnColor, dragColor); drawHeader.drawBaseFill(columnColor, dragColor); - drawHeader.drawEye(); - drawHeader.drawPreviewToggle(column ? column->getOpacity() : 0); + if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + drawHeader.drawUnifiedViewToggle(column ? column->getOpacity() : 0); + else { + drawHeader.drawEye(); + drawHeader.drawPreviewToggle(column ? column->getOpacity() : 0); + } drawHeader.drawLock(); drawHeader.drawColumnName(); drawHeader.drawColumnNumber(); @@ -1655,37 +1671,10 @@ void ColumnArea::drawLevelColumnHead(QPainter &p, int col) { //----------------------------------------------------------------------------- void ColumnArea::drawSoundColumnHead(QPainter &p, int col) { // AREA - TColumnSelection *selection = m_viewer->getColumnSelection(); - const Orientation *o = m_viewer->orientation(); - - int x = m_viewer->columnToLayerAxis(col); - - p.setRenderHint(QPainter::SmoothPixmapTransform, true); - QString fontName = Preferences::instance()->getInterfaceFont(); - if (fontName == "") { -#ifdef _WIN32 - fontName = "Arial"; -#else - fontName = "Helvetica"; -#endif - } - static QFont font(fontName, -1, QFont::Normal); - font.setPixelSize(XSHEET_FONT_PX_SIZE); - p.setFont(font); - TXsheet *xsh = m_viewer->getXsheet(); TXshSoundColumn *sc = xsh->getColumn(col) ? xsh->getColumn(col)->getSoundColumn() : 0; - QPoint orig = m_viewer->positionToXY(CellPosition(0, col)); - QRect rect = m_viewer->orientation() - ->rect(PredefinedRect::LAYER_HEADER) - .translated(orig); - - QPoint columnNamePos = orig + QPoint(12, o->cellHeight()); - - bool isCurrent = m_viewer->getCurrentColumn() == col; - DrawHeader drawHeader(this, p, col); drawHeader.prepare(); QColor columnColor, dragColor; @@ -1710,36 +1699,6 @@ void ColumnArea::drawSoundColumnHead(QPainter &p, int col) { // AREA //----------------------------------------------------------------------------- void ColumnArea::drawPaletteColumnHead(QPainter &p, int col) { // AREA - TColumnSelection *selection = m_viewer->getColumnSelection(); - const Orientation *o = m_viewer->orientation(); - - QPoint orig = m_viewer->positionToXY(CellPosition(0, std::max(col, -1))); - - QString fontName = Preferences::instance()->getInterfaceFont(); - if (fontName == "") { -#ifdef _WIN32 - fontName = "Arial"; -#else - fontName = "Helvetica"; -#endif - } - static QFont font(fontName, -1, QFont::Normal); - font.setPixelSize(XSHEET_FONT_PX_SIZE); - - p.setFont(font); - p.setRenderHint(QPainter::SmoothPixmapTransform, true); - - int currentColumnIndex = m_viewer->getCurrentColumn(); - int x = m_viewer->columnToLayerAxis(col); - - QRect rect(x, 0, o->cellWidth(), height()); - - TXsheet *xsh = m_viewer->getXsheet(); - - bool isEmpty = false; - if (col >= 0) // Verifico se la colonna e' vuota - isEmpty = xsh->isColumnEmpty(col); - DrawHeader drawHeader(this, p, col); drawHeader.prepare(); QColor columnColor, dragColor; @@ -2417,8 +2376,27 @@ void ColumnArea::mousePressEvent(QMouseEvent *event) { if (event->button() != Qt::LeftButton) return; m_doOnRelease = isCtrlPressed ? ToggleAllLock : ToggleLock; } - // preview button - else if (o->rect(PredefinedRect::EYE_AREA).contains(mouseInCell)) { + // unified view button + else if (Preferences::instance() + ->isUnifyColumnVisibilityTogglesEnabled() && + o->rect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA) + .contains(mouseInCell)) { + if (event->button() != Qt::LeftButton) return; + if (column->getSoundTextColumn()) { + // do nothing + } else { + // sync eye button on release + m_doOnRelease = + isCtrlPressed ? ToggleAllTransparency : ToggleTransparency; + if (!o->flag(PredefinedFlag::CONFIG_AREA_VISIBLE) && + !column->getSoundColumn()) + startTransparencyPopupTimer(event); + } + } + // separated view - preview button + else if (!Preferences::instance() + ->isUnifyColumnVisibilityTogglesEnabled() && + o->rect(PredefinedRect::EYE_AREA).contains(mouseInCell)) { if (event->button() != Qt::LeftButton) return; if (column->getSoundTextColumn()) { // do nothing @@ -2429,8 +2407,10 @@ void ColumnArea::mousePressEvent(QMouseEvent *event) { TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged(); } } - // camstand button - else if (o->rect(PredefinedRect::PREVIEW_LAYER_AREA) + // separated view - camstand button + else if (!Preferences::instance() + ->isUnifyColumnVisibilityTogglesEnabled() && + o->rect(PredefinedRect::PREVIEW_LAYER_AREA) .contains(mouseInCell)) { if (event->button() != Qt::LeftButton) return; if (column->getPaletteColumn() || column->getSoundTextColumn()) { @@ -2683,6 +2663,10 @@ void ColumnArea::mouseReleaseEvent(QMouseEvent *event) { TXshColumn *column = xsh->getColumn(m_col); if (m_doOnRelease == ToggleTransparency) { column->setCamstandVisible(!column->isCamstandVisible()); + // sync eye button + if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + column->setPreviewVisible(column->isCamstandVisible()); + if (column->getSoundColumn()) app->getCurrentXsheet()->notifyXsheetSoundChanged(); } else if (m_doOnRelease == TogglePreviewVisible) @@ -2757,6 +2741,9 @@ void ColumnArea::mouseReleaseEvent(QMouseEvent *event) { if (!xsh->isColumnEmpty(col) && !column->getPaletteColumn() && !column->getSoundTextColumn()) { column->setCamstandVisible(!column->isCamstandVisible()); + // sync eye button + if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + column->setPreviewVisible(column->isCamstandVisible()); if (column->getSoundColumn()) sound_changed = true; } } @@ -2781,10 +2768,12 @@ void ColumnArea::mouseReleaseEvent(QMouseEvent *event) { // if necessary. it causes slowness when opening preview flipbook of large // scene. // KNOWN BUG: Side effect, transparency doesn't sync in schematic if false. - bool isTransparencyRendered = app->getCurrentScene() - ->getScene() - ->getProperties() - ->isColumnColorFilterOnRenderEnabled(); + bool isTransparencyRendered = + app->getCurrentScene() + ->getScene() + ->getProperties() + ->isColumnColorFilterOnRenderEnabled() || + Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled(); bool isStateChanged = m_doOnRelease == TogglePreviewVisible || m_doOnRelease == ToggleAllPreviewVisible || m_doOnRelease == ToggleLock || @@ -2823,7 +2812,10 @@ void ColumnArea::mouseDoubleClickEvent(QMouseEvent *event) { if (!nameRect.contains(mouseInCell)) return; TXsheet *xsh = m_viewer->getXsheet(); - if (col >= 0 && xsh->isColumnEmpty(col)) return; + // enable to rename empty column when the column name is linked to the level + if (!Preferences::instance()->isLinkColumnNameWithLevelEnabled() && + col >= 0 && xsh->isColumnEmpty(col)) + return; QPoint fieldPos = (col < 0 && o->isVerticalTimeline()) ? nameRect.topLeft() : topLeft; @@ -2858,9 +2850,10 @@ void ColumnArea::contextMenuEvent(QContextMenuEvent *event) { QMenu menu(this); CommandManager *cmdManager = CommandManager::instance(); - //---- Preview + //---- Unified if (((isCamera && !o->isVerticalTimeline()) || !xsh->isColumnEmpty(col)) && - o->rect(PredefinedRect::EYE_AREA).contains(mouseInCell)) { + o->rect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA).contains(mouseInCell) && + Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) { menu.setObjectName("xsheetColumnAreaMenu_Preview"); menu.addAction(cmdManager->getAction("MI_EnableThisColumnOnly")); @@ -2870,24 +2863,25 @@ void ColumnArea::contextMenuEvent(QContextMenuEvent *event) { menu.addAction(cmdManager->getAction("MI_DisableSelectedColumns")); menu.addAction(cmdManager->getAction("MI_SwapEnabledColumns")); } - //---- Lock - else if ((isCamera || !xsh->isColumnEmpty(col)) && - o->rect((isCamera) ? PredefinedRect::CAMERA_LOCK_AREA - : PredefinedRect::LOCK_AREA) - .contains(mouseInCell)) { - menu.setObjectName("xsheetColumnAreaMenu_Lock"); + //---- Preview + else if (((isCamera && !o->isVerticalTimeline()) || + !xsh->isColumnEmpty(col)) && + o->rect(PredefinedRect::EYE_AREA).contains(mouseInCell) && + !Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) { + menu.setObjectName("xsheetColumnAreaMenu_Preview"); - menu.addAction(cmdManager->getAction("MI_LockThisColumnOnly")); - menu.addAction(cmdManager->getAction("MI_LockSelectedColumns")); - menu.addAction(cmdManager->getAction("MI_LockAllColumns")); - menu.addAction(cmdManager->getAction("MI_UnlockSelectedColumns")); - menu.addAction(cmdManager->getAction("MI_UnlockAllColumns")); - menu.addAction(cmdManager->getAction("MI_ToggleColumnLocks")); + menu.addAction(cmdManager->getAction("MI_EnableThisColumnOnly")); + menu.addAction(cmdManager->getAction("MI_EnableSelectedColumns")); + menu.addAction(cmdManager->getAction("MI_EnableAllColumns")); + menu.addAction(cmdManager->getAction("MI_DisableAllColumns")); + menu.addAction(cmdManager->getAction("MI_DisableSelectedColumns")); + menu.addAction(cmdManager->getAction("MI_SwapEnabledColumns")); } //---- Camstand else if (((isCamera && !o->isVerticalTimeline()) || !xsh->isColumnEmpty(col)) && - o->rect(PredefinedRect::PREVIEW_LAYER_AREA).contains(mouseInCell)) { + o->rect(PredefinedRect::PREVIEW_LAYER_AREA).contains(mouseInCell) && + !Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) { menu.setObjectName("xsheetColumnAreaMenu_Camstand"); menu.addAction(cmdManager->getAction("MI_ActivateThisColumnOnly")); @@ -2899,6 +2893,20 @@ void ColumnArea::contextMenuEvent(QContextMenuEvent *event) { // hide all columns placed on the left menu.addAction(cmdManager->getAction("MI_DeactivateUpperColumns")); } + //---- Lock + else if ((isCamera || !xsh->isColumnEmpty(col)) && + o->rect((isCamera) ? PredefinedRect::CAMERA_LOCK_AREA + : PredefinedRect::LOCK_AREA) + .contains(mouseInCell)) { + menu.setObjectName("xsheetColumnAreaMenu_Lock"); + + menu.addAction(cmdManager->getAction("MI_LockThisColumnOnly")); + menu.addAction(cmdManager->getAction("MI_LockSelectedColumns")); + menu.addAction(cmdManager->getAction("MI_LockAllColumns")); + menu.addAction(cmdManager->getAction("MI_UnlockSelectedColumns")); + menu.addAction(cmdManager->getAction("MI_UnlockAllColumns")); + menu.addAction(cmdManager->getAction("MI_ToggleColumnLocks")); + } // right clicking another area / right clicking empty column head else { if (!isCamera) { diff --git a/toonz/sources/toonz/xshcolumnviewer.h b/toonz/sources/toonz/xshcolumnviewer.h index bad711f..ea091b6 100644 --- a/toonz/sources/toonz/xshcolumnviewer.h +++ b/toonz/sources/toonz/xshcolumnviewer.h @@ -321,6 +321,7 @@ class ColumnArea final : public QWidget { bool isEmpty, isCurrent; TXshColumn *column; QPoint orig; + TXshLevel *reservedLevel; public: DrawHeader(ColumnArea *area, QPainter &p, int col); @@ -334,6 +335,7 @@ class ColumnArea final : public QWidget { void drawBaseFill(const QColor &columnColor, const QColor &dragColor) const; void drawEye() const; void drawPreviewToggle(int opacity) const; + void drawUnifiedViewToggle(int opacity) const; void drawLock() const; void drawConfig() const; void drawColumnNumber() const; diff --git a/toonz/sources/toonz/xsheetviewer.cpp b/toonz/sources/toonz/xsheetviewer.cpp index adbe05e..56afdc0 100644 --- a/toonz/sources/toonz/xsheetviewer.cpp +++ b/toonz/sources/toonz/xsheetviewer.cpp @@ -208,6 +208,12 @@ void XsheetViewer::getButton(const int &btype, QColor &bgColor, iconImage = (isTimeline) ? getTimelineConfigButtonImage() : getXsheetConfigButtonImage(); break; + case UNIFIED_TRANSP_XSHBUTTON: + bgColor = (isTimeline) ? getTimelinePreviewButtonBgOnColor() + : getXsheetPreviewButtonBgOnColor(); + iconImage = (isTimeline) ? getTimelineUnifiedButtonTranspImage() + : getXsheetUnifiedButtonTranspImage(); + break; default: bgColor = grey210; static QImage iconignored; @@ -1266,25 +1272,42 @@ void XsheetViewer::keyPressEvent(QKeyEvent *event) { // selection range. if (Preferences::instance()->isUseArrowKeyToShiftCellSelectionEnabled() && cellSel && !cellSel->isEmpty()) { - int r0, c0, r1, c1; - cellSel->getSelectedCells(r0, c0, r1, c1); + int rowA, colA, rowB, colB; + cellSel->getSelectedCells(rowA, colA, rowB, colB); stride.setFrame(cellSel->getSelectedCells().getRowCount()); if (m_cellArea->isControlPressed()) { // resize - if (r0 == r1 && shift.frame() < 0) return; - if (c0 == c1 && shift.layer() < firstCol) return; - cellSel->selectCells(r0, c0, r1 + shift.frame(), c1 + shift.layer()); + + // resize selection of frames/rows forward or backwards + assert(cellSel->getResizePivotRow() >= 0); + if (rowA < cellSel->getResizePivotRow()) + rowA += shift.frame(); + else + rowB += shift.frame(); + + // resize selection of layers/columns "up" or "down" + if (colA < getCurrentColumn()) + colA += shift.layer(); + else + colB += shift.layer(); + + // keep selection inside the xsheet/timeline + if (colA < firstCol || colB < firstCol || rowA < 0 || rowB < 0) return; + + // apply new selection rectangle + cellSel->selectCells(rowA, colA, rowB, colB); updateCells(); TApp::instance()->getCurrentSelection()->notifySelectionChanged(); return; + } else { // shift CellPosition offset(shift * stride); - int movedR0 = std::max(0, r0 + offset.frame()); - int movedC0 = std::max(firstCol, c0 + offset.layer()); - int diffFrame = movedR0 - r0; - int diffLayer = movedC0 - c0; - cellSel->selectCells(r0 + diffFrame, c0 + diffLayer, r1 + diffFrame, - c1 + diffLayer); + int movedRow0 = std::max(0, rowA + offset.frame()); + int movedCol0 = std::max(firstCol, colA + offset.layer()); + int diffRow = movedRow0 - rowA; + int diffCol = movedCol0 - colA; + cellSel->selectCells(rowA + diffRow, colA + diffCol, rowB + diffRow, + colB + diffCol); TApp::instance()->getCurrentSelection()->notifySelectionChanged(); } } diff --git a/toonz/sources/toonz/xsheetviewer.h b/toonz/sources/toonz/xsheetviewer.h index 6e6393d..515148d 100644 --- a/toonz/sources/toonz/xsheetviewer.h +++ b/toonz/sources/toonz/xsheetviewer.h @@ -40,7 +40,8 @@ enum TXshButtonType { CAMSTAND_TRANSP_XSHBUTTON, LOCK_ON_XSHBUTTON, LOCK_OFF_XSHBUTTON, - CONFIG_XSHBUTTON + CONFIG_XSHBUTTON, + UNIFIED_TRANSP_XSHBUTTON }; namespace XsheetGUI { @@ -241,9 +242,9 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings { Q_PROPERTY(QColor TextColor READ getTextColor WRITE setTextColor) Q_PROPERTY( QColor ErrorTextColor READ getErrorTextColor WRITE setErrorTextColor) - Q_PROPERTY(QColor SelectedTextColor READ getCurrentFrameTextColor WRITE + Q_PROPERTY(QColor CurrentFrameTextColor READ getCurrentFrameTextColor WRITE setCurrentFrameTextColor) - Q_PROPERTY(QColor CurrentFrameTextColor READ getSelectedTextColor WRITE + Q_PROPERTY(QColor SelectedTextColor READ getSelectedTextColor WRITE setSelectedTextColor) Q_PROPERTY(QColor PreviewFrameTextColor READ getPreviewFrameTextColor WRITE setPreviewFrameTextColor) @@ -449,6 +450,7 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings { QImage m_xsheetPreviewButtonOnImage; QColor m_xsheetPreviewButtonBgOffColor; QImage m_xsheetPreviewButtonOffImage; + QImage m_xsheetUnifiedButtonTranspImage; Q_PROPERTY( QColor XsheetPreviewButtonBgOnColor READ getXsheetPreviewButtonBgOnColor WRITE setXsheetPreviewButtonBgOnColor) @@ -461,6 +463,9 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings { Q_PROPERTY( QImage XsheetPreviewButtonOffImage READ getXsheetPreviewButtonOffImage WRITE setXsheetPreviewButtonOffImage) + Q_PROPERTY(QImage XsheetUnifiedButtonTranspImage READ + getXsheetUnifiedButtonTranspImage WRITE + setXsheetUnifiedButtonTranspImage) // Xsheet Camstand Button QColor m_xsheetCamstandButtonBgOnColor; QImage m_xsheetCamstandButtonOnImage; @@ -508,6 +513,7 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings { QImage m_timelinePreviewButtonOnImage; QColor m_timelinePreviewButtonBgOffColor; QImage m_timelinePreviewButtonOffImage; + QImage m_timelineUnifiedButtonTranspImage; Q_PROPERTY(QColor TimelinePreviewButtonBgOnColor READ getTimelinePreviewButtonBgOnColor WRITE setTimelinePreviewButtonBgOnColor) @@ -520,6 +526,9 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings { Q_PROPERTY( QImage TimelinePreviewButtonOffImage READ getTimelinePreviewButtonOffImage WRITE setTimelinePreviewButtonOffImage) + Q_PROPERTY(QImage TimelineUnifiedButtonTranspImage READ + getTimelineUnifiedButtonTranspImage WRITE + setTimelineUnifiedButtonTranspImage) // Timeline Camstand Button QColor m_timelineCamstandButtonBgOnColor; QImage m_timelineCamstandButtonOnImage; @@ -1098,6 +1107,9 @@ public: void setXsheetPreviewButtonOffImage(const QImage &image) { m_xsheetPreviewButtonOffImage = image; } + void setXsheetUnifiedButtonTranspImage(const QImage &image) { + m_xsheetUnifiedButtonTranspImage = image; + } QColor getXsheetPreviewButtonBgOnColor() const { return m_xsheetPreviewButtonBgOnColor; } @@ -1110,6 +1122,9 @@ public: QImage getXsheetPreviewButtonOffImage() const { return m_xsheetPreviewButtonOffImage; } + QImage getXsheetUnifiedButtonTranspImage() const { + return m_xsheetUnifiedButtonTranspImage; + } // Xsheet Camstand Button void setXsheetCamstandButtonBgOnColor(const QColor &color) { m_xsheetCamstandButtonBgOnColor = color; @@ -1192,6 +1207,9 @@ public: void setTimelinePreviewButtonOffImage(const QImage &image) { m_timelinePreviewButtonOffImage = image; } + void setTimelineUnifiedButtonTranspImage(const QImage &image) { + m_timelineUnifiedButtonTranspImage = image; + } QColor getTimelinePreviewButtonBgOnColor() const { return m_timelinePreviewButtonBgOnColor; } @@ -1204,6 +1222,9 @@ public: QImage getTimelinePreviewButtonOffImage() const { return m_timelinePreviewButtonOffImage; } + QImage getTimelineUnifiedButtonTranspImage() const { + return m_timelineUnifiedButtonTranspImage; + } // Timeline Camstand Button void setTimelineCamstandButtonBgOnColor(const QColor &color) { m_timelineCamstandButtonBgOnColor = color; diff --git a/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp b/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp index 836266b..28fd4b2 100644 --- a/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp +++ b/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp @@ -368,8 +368,8 @@ static QString getExeName(bool isComposer) { return name + ".exe "; #elif defined(MACOSX) TVER::ToonzVersion tver; - return "\"./" + QString::fromStdString(tver.getAppName()) + - ".app/Contents/MacOS/" + name + "\" "; + return QString::fromStdString(tver.getAppName()) + ".app/Contents/MacOS/" + + name; #else return name; #endif @@ -541,6 +541,59 @@ QString TFarmTask::getCommandLineArguments() const { return cmdline; } +QStringList TFarmTask::getCommandLineArgumentsList() const { + QStringList ret; + + if (!m_taskFilePath.isEmpty()) + ret << QString::fromStdWString( + TSystem::toUNC(m_taskFilePath).getWideString()); + + if (m_callerMachineName != "") { + struct hostent *he = gethostbyname(m_callerMachineName.toLatin1()); + if (he) { + char *ipAddress = inet_ntoa(*(struct in_addr *)*(he->h_addr_list)); + ret << "-tmsg" << QString::fromUtf8(ipAddress); + } + } + + if (!m_isComposerTask) { + if (m_overwrite == Overwrite_All) + ret << "-overwriteAll"; + else if (m_overwrite == Overwrite_NoPaint) + ret << "-overwriteNoPaint"; + if (m_onlyVisible) ret << "-onlyvisible"; + return ret; + } + + if (!m_outputPath.isEmpty()) { + TFilePath outputPath; + try { + outputPath = TSystem::toUNC(m_outputPath); + } catch (TException &) { + } + + ret << "-o" << QString::fromStdWString(outputPath.getWideString()); + } + + ret << "-range" << QString::number(m_from) << QString::number(m_to); + ret << "-step" << QString::number(m_step); + ret << "-shrink" << QString::number(m_shrink); + ret << "-multimedia" << QString::number(m_multimedia); + + const QString threadCounts[3] = {"single", "half", "all"}; + ret << "-nthreads" << threadCounts[m_threadsIndex]; + + const QString maxTileSizes[4] = { + "none", QString::number(TOutputProperties::LargeVal), + QString::number(TOutputProperties::MediumVal), + QString::number(TOutputProperties::SmallVal)}; + ret << "-maxtilesize" << maxTileSizes[m_maxTileSizeIndex]; + + QString appname = QSettings().applicationName(); + + return ret; +} + QString TFarmTask::getCommandLine(bool) const { return getCommandLinePrgName() + getCommandLineArguments(); } diff --git a/toonz/sources/toonzlib/orientation.cpp b/toonz/sources/toonzlib/orientation.cpp index c7dea3c..4b9a203 100644 --- a/toonz/sources/toonzlib/orientation.cpp +++ b/toonz/sources/toonzlib/orientation.cpp @@ -438,9 +438,9 @@ TopToBottomOrientation::TopToBottomOrientation() { static int HDRROW3; static int HDRROW4; static int HDRROW5; - QRect layername, eyeArea, previewArea, lockArea, cameraLockArea, configArea, - cameraConfigArea, thumbnailArea, thumbnail, cameraIconArea, pegbarname, - volumeArea; + QRect layername, eyeArea, previewArea, unifiedViewArea, lockArea, + cameraLockArea, configArea, cameraConfigArea, thumbnailArea, thumbnail, + cameraIconArea, pegbarname, volumeArea; QPoint soundTopLeft; if (layout == QString("Minimum")) { @@ -473,6 +473,12 @@ TopToBottomOrientation::TopToBottomOrientation() { addRect(PredefinedRect::PREVIEW_LAYER, iconRect(previewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1)); + unifiedViewArea = QRect( + INDENT, HDRROW2, eyeArea.width() + previewArea.width(), HDRROW_HEIGHT); + addRect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA, unifiedViewArea); + addRect(PredefinedRect::UNIFIEDVIEW_LAYER, + iconRect(unifiedViewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1)); + addRect(PredefinedRect::LOCK_AREA, QRect(0, 0, -1, -1)); addRect(PredefinedRect::LOCK, QRect(0, 0, -1, -1)); addRect(PredefinedRect::CAMERA_LOCK_AREA, QRect(0, 0, -1, -1)); @@ -559,6 +565,12 @@ TopToBottomOrientation::TopToBottomOrientation() { addRect(PredefinedRect::PREVIEW_LAYER, iconRect(previewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1)); + unifiedViewArea = QRect( + INDENT, HDRROW2, eyeArea.width() + previewArea.width(), HDRROW_HEIGHT); + addRect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA, unifiedViewArea); + addRect(PredefinedRect::UNIFIEDVIEW_LAYER, + iconRect(unifiedViewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1)); + lockArea = QRect(INDENT + eyeArea.width() + previewArea.width(), HDRROW2, ICON_WIDTH, HDRROW_HEIGHT); addRect(PredefinedRect::LOCK_AREA, lockArea); @@ -670,6 +682,12 @@ TopToBottomOrientation::TopToBottomOrientation() { addRect(PredefinedRect::PREVIEW_LAYER, iconRect(previewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1)); + unifiedViewArea = + QRect(INDENT, HDRROW2, CELL_WIDTH - ICON_WIDTH, HDRROW_HEIGHT * 2); + addRect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA, unifiedViewArea); + addRect(PredefinedRect::UNIFIEDVIEW_LAYER, + iconRect(unifiedViewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1)); + lockArea = QRect(INDENT + eyeArea.width(), HDRROW2, ICON_WIDTH, HDRROW_HEIGHT); addRect(PredefinedRect::LOCK_AREA, lockArea); @@ -781,6 +799,13 @@ TopToBottomOrientation::TopToBottomOrientation() { addRect(PredefinedRect::PREVIEW_LAYER, previewArea.adjusted(previewArea.width() - ICON_WIDTH, 0, 0, 0)); + unifiedViewArea = + QRect(INDENT, HDRROW2, CELL_WIDTH - INDENT - 2, HDRROW_HEIGHT - 1); + addRect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA, unifiedViewArea); + addRect(PredefinedRect::UNIFIEDVIEW_LAYER, + unifiedViewArea.adjusted(unifiedViewArea.width() - ICON_WIDTH, 0, 0, + 0)); + lockArea = QRect(INDENT, HDRROW2, ICON_WIDTH - 1, HDRROW_HEIGHT - 1); addRect(PredefinedRect::LOCK_AREA, lockArea); addRect(PredefinedRect::LOCK, lockArea); @@ -1216,7 +1241,6 @@ LeftToRightOrientation::LeftToRightOrientation() { (FRAME_HEADER_HEIGHT - NAV_TAG_HEIGHT) / 2, NAV_TAG_WIDTH, NAV_TAG_HEIGHT)); - // Column viewer addRect(PredefinedRect::LAYER_HEADER, QRect(1, 0, LAYER_HEADER_WIDTH - 2, CELL_HEIGHT)); @@ -1238,6 +1262,10 @@ LeftToRightOrientation::LeftToRightOrientation() { eyeArea.translated(ICON_OFFSET, 0)); addRect(PredefinedRect::PREVIEW_LAYER, eye.translated(ICON_OFFSET, 0).adjusted(1, 1, -1, -1)); + + addRect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA, eyeArea); + addRect(PredefinedRect::UNIFIEDVIEW_LAYER, eye.adjusted(1, 1, -1, -1)); + addRect(PredefinedRect::LOCK_AREA, eyeArea.translated(2 * ICON_OFFSET, 0)); addRect(PredefinedRect::LOCK, eye.translated(2 * ICON_OFFSET, 0).adjusted(1, 1, -1, -1)); diff --git a/toonz/sources/toonzlib/preferences.cpp b/toonz/sources/toonzlib/preferences.cpp index 288a26c..fd28142 100644 --- a/toonz/sources/toonzlib/preferences.cpp +++ b/toonz/sources/toonzlib/preferences.cpp @@ -586,6 +586,8 @@ void Preferences::definePreferenceItems() { define(showXSheetToolbar, "showXSheetToolbar", QMetaType::Bool, true); define(expandFunctionHeader, "expandFunctionHeader", QMetaType::Bool, false); define(showColumnNumbers, "showColumnNumbers", QMetaType::Bool, false); + define(unifyColumnVisibilityToggles, "unifyColumnVisibilityToggles", + QMetaType::Bool, false); define(parentColorsInXsheetColumn, "parentColorsInXsheetColumn", QMetaType::Bool, false); define(highlightLineEverySecond, "highlightLineEverySecond", QMetaType::Bool, @@ -602,6 +604,14 @@ void Preferences::definePreferenceItems() { 0); // default define(showFrameNumberWithLetters, "showFrameNumberWithLetters", QMetaType::Bool, false); + // This option will do the following: + // - When setting a cell in the empty column, level name will be copied to the + // column name + // - Typing the cell without level name in the empty column will try to use a + // level with the same name as the column The behavior may be changed in the + // future development. + define(linkColumnNameWithLevel, "linkColumnNameWithLevel", QMetaType::Bool, + false); // Animation define(keyframeType, "keyframeType", QMetaType::Int, 2); // Linear diff --git a/toonz/sources/toonzlib/txsheet.cpp b/toonz/sources/toonzlib/txsheet.cpp index 4484322..79f139e 100644 --- a/toonz/sources/toonzlib/txsheet.cpp +++ b/toonz/sources/toonzlib/txsheet.cpp @@ -302,6 +302,13 @@ bool TXsheet::setCell(int row, int col, const TXshCell &cell) { else if (row >= m_imp->m_frameCount) m_imp->m_frameCount = row + 1; + // set the level name to the column + if (wasColumnEmpty && cellColumn && !cell.isEmpty() && + Preferences::instance()->isLinkColumnNameWithLevelEnabled()) { + getStageObject(TStageObjectId::ColumnId(col)) + ->setName(to_string(cell.m_level->getName())); + } + TNotifier::instance()->notify(TXsheetChange()); return true; @@ -386,6 +393,14 @@ bool TXsheet::setCells(int row, int col, int rowCount, const TXshCell cells[]) { newColRowCount < m_imp->m_frameCount) updateFrameCount(); } + row + 1; + + // set the level name to the column + if (wasColumnEmpty && i < rowCount && + Preferences::instance()->isLinkColumnNameWithLevelEnabled()) { + getStageObject(TStageObjectId::ColumnId(col)) + ->setName(to_string(cells[i].m_level->getName())); + } return true; } diff --git a/toonz/sources/toonzlib/txshlevelcolumn.cpp b/toonz/sources/toonzlib/txshlevelcolumn.cpp index 7774465..da2a46f 100644 --- a/toonz/sources/toonzlib/txshlevelcolumn.cpp +++ b/toonz/sources/toonzlib/txshlevelcolumn.cpp @@ -209,9 +209,12 @@ void TXshLevelColumn::saveData(TOStream &os) { //----------------------------------------------------------------------------- // Used in TCellData::getNumbers -bool TXshLevelColumn::setNumbers(int row, int rowCount, - const TXshCell cells[]) { - if (m_cells.empty()) return false; +// reservedLevel can be nonzero if the preferences option +// "LinkColumnNameWithLevel" is ON and the column name is the same as some level +// in the scene cast. +bool TXshLevelColumn::setNumbers(int row, int rowCount, const TXshCell cells[], + TXshLevel *reservedLevel) { + if (m_cells.empty() && !reservedLevel) return false; // Check availability. // - if source cells are all empty, do nothing // - also, if source or target cells contain NO_FRAME, do nothing @@ -236,16 +239,18 @@ bool TXshLevelColumn::setNumbers(int row, int rowCount, // Find a level to input. // If the first target cell is empty, search the upper cells, and lower cells // and use a level of firsty-found occupied neighbor cell. - TXshLevelP currentLevel; - int tmpIndex = std::min(row - m_first, (int)m_cells.size() - 1); + TXshLevelP currentLevel = reservedLevel; + int tmpIndex = std::min(row - m_first, (int)m_cells.size() - 1); // search upper cells - while (tmpIndex >= 0) { - TXshCell tmpCell = m_cells[tmpIndex]; - if (!tmpCell.isEmpty() && tmpCell.m_frameId != TFrameId::NO_FRAME) { - currentLevel = tmpCell.m_level; - break; + if (!currentLevel) { + while (tmpIndex >= 0) { + TXshCell tmpCell = m_cells[tmpIndex]; + if (!tmpCell.isEmpty() && tmpCell.m_frameId != TFrameId::NO_FRAME) { + currentLevel = tmpCell.m_level; + break; + } + tmpIndex--; } - tmpIndex--; } // if not found any level in upper cells, then search the lower cells if (!currentLevel) { diff --git a/toonz/sources/toonzlib/txshsoundcolumn.cpp b/toonz/sources/toonzlib/txshsoundcolumn.cpp index 34b2c73..d84fa3e 100644 --- a/toonz/sources/toonzlib/txshsoundcolumn.cpp +++ b/toonz/sources/toonzlib/txshsoundcolumn.cpp @@ -447,7 +447,7 @@ bool TXshSoundColumn::setCell(int row, const TXshCell &cell, if (isBeforeLevelInSequence) { int oldEndOffset = lBefore->getEndOffset(); int endOffset = (lBefore->getVisibleEndFrame() != row) ? oldEndOffset - 1 - : oldEndOffset; + : oldEndOffset; if (isNextLevelInSequence) { endOffset = lNext->getEndOffset(); // Se precedente e successivo sono diversi elimino il successivo (caso in @@ -468,8 +468,8 @@ bool TXshSoundColumn::setCell(int row, const TXshCell &cell, if (isNextLevelInSequence) { int oldStartOffset = lNext->getStartOffset(); int startOffset = (lNext->getVisibleStartFrame() != row) - ? oldStartOffset - 1 - : oldStartOffset; + ? oldStartOffset - 1 + : oldStartOffset; if (l && l != lNext) { if (l->getVisibleFrameCount() == 1) removeColumnLevel(l); diff --git a/toonz/sources/toonzqt/dvdialog.cpp b/toonz/sources/toonzqt/dvdialog.cpp index ee892a1..2d9c19d 100644 --- a/toonz/sources/toonzqt/dvdialog.cpp +++ b/toonz/sources/toonzqt/dvdialog.cpp @@ -807,7 +807,7 @@ MessageAndCheckboxDialog::MessageAndCheckboxDialog( //============================================================================= -void MessageAndCheckboxDialog::onButtonPressed(int id) { done(id); } +void MessageAndCheckboxDialog::onButtonClicked(int id) { done(id); } //============================================================================= @@ -849,9 +849,9 @@ RadioButtonDialog::RadioButtonDialog(const QString &labelText, endVLayout(); QPushButton *applyButton = new QPushButton(QObject::tr("Apply")); - ret = ret && connect(applyButton, SIGNAL(pressed()), this, SLOT(onApply())); + ret = ret && connect(applyButton, SIGNAL(clicked()), this, SLOT(onApply())); QPushButton *cancelButton = new QPushButton(QObject::tr("Cancel")); - ret = ret && connect(cancelButton, SIGNAL(pressed()), this, SLOT(onCancel())); + ret = ret && connect(cancelButton, SIGNAL(clicked()), this, SLOT(onCancel())); addButtonBarWidget(applyButton, cancelButton); @@ -922,9 +922,9 @@ void ProgressDialog::setLabelText(const QString &text) { void ProgressDialog::setCancelButton(QPushButton *cancelButton) { m_cancelButton = cancelButton; - bool ret = connect(cancelButton, SIGNAL(pressed()), this, SLOT(onCancel())); + bool ret = connect(cancelButton, SIGNAL(clicked()), this, SLOT(onCancel())); ret = - ret && connect(cancelButton, SIGNAL(pressed()), this, SIGNAL(canceled())); + ret && connect(cancelButton, SIGNAL(clicked()), this, SIGNAL(canceled())); assert(ret); addButtonBarWidget(m_cancelButton); } @@ -1014,7 +1014,7 @@ int DVGui::MsgBox(MsgType type, const QString &text, buttonGroup->addButton(button, i + 1); } - QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), &dialog, + QObject::connect(buttonGroup, SIGNAL(idClicked(int)), &dialog, SLOT(done(int))); dialog.raise(); @@ -1064,7 +1064,7 @@ void DVGui::MsgBoxInPopup(MsgType type, const QString &text) { button->setDefault(true); dialog.addButtonBarWidget(button); buttonGroup->addButton(button, 1); - QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), &dialog, + QObject::connect(buttonGroup, SIGNAL(idClicked(int)), &dialog, SLOT(done(int))); while (!messageQueue.empty()) { @@ -1138,7 +1138,7 @@ int DVGui::MsgBox(const QString &text, const QString &button1Text, dialog.addButtonBarWidget(button3); buttonGroup->addButton(button3, 3); - QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), &dialog, + QObject::connect(buttonGroup, SIGNAL(idClicked(int)), &dialog, SLOT(done(int))); dialog.raise(); return dialog.exec(); @@ -1197,7 +1197,7 @@ int DVGui::MsgBox(const QString &text, const QString &button1Text, dialog.addButtonBarWidget(button4); buttonGroup->addButton(button4, 4); - QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), &dialog, + QObject::connect(buttonGroup, SIGNAL(idClicked(int)), &dialog, SLOT(done(int))); dialog.raise(); return dialog.exec(); @@ -1258,7 +1258,7 @@ Dialog *DVGui::createMsgBox(MsgType type, const QString &text, buttonGroup->addButton(button, i + 1); } - QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), dialog, + QObject::connect(buttonGroup, SIGNAL(idClicked(int)), dialog, SLOT(done(int))); return dialog; @@ -1317,8 +1317,8 @@ MessageAndCheckboxDialog *DVGui::createMsgandCheckbox( QObject::connect(dialogCheckBox, SIGNAL(stateChanged(int)), dialog, SLOT(onCheckboxChanged(int))); - QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), dialog, - SLOT(onButtonPressed(int))); + QObject::connect(buttonGroup, SIGNAL(idClicked(int)), dialog, + SLOT(onButtonClicked(int))); return dialog; } diff --git a/toonz/sources/toonzqt/fxschematicnode.cpp b/toonz/sources/toonzqt/fxschematicnode.cpp index e3b9707..f757fc2 100644 --- a/toonz/sources/toonzqt/fxschematicnode.cpp +++ b/toonz/sources/toonzqt/fxschematicnode.cpp @@ -2821,8 +2821,11 @@ FxSchematicZeraryNode::FxSchematicZeraryNode(FxSchematicScene *scene, connect(m_nameItem, SIGNAL(focusOut()), this, SLOT(onNameChanged())); connect(m_renderToggle, SIGNAL(toggled(bool)), this, SLOT(onRenderToggleClicked(bool))); - connect(m_cameraStandToggle, SIGNAL(stateChanged(int)), this, - SLOT(onCameraStandToggleClicked(int))); + if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + m_cameraStandToggle->hide(); + else + connect(m_cameraStandToggle, SIGNAL(stateChanged(int)), this, + SLOT(onCameraStandToggleClicked(int))); if (zeraryFx) { int i, inputPorts = zeraryFx->getInputPortCount(); @@ -3085,8 +3088,11 @@ FxSchematicColumnNode::FxSchematicColumnNode(FxSchematicScene *scene, connect(m_nameItem, SIGNAL(focusOut()), this, SLOT(onNameChanged())); ret = ret && connect(m_renderToggle, SIGNAL(toggled(bool)), this, SLOT(onRenderToggleClicked(bool))); - ret = ret && connect(m_cameraStandToggle, SIGNAL(stateChanged(int)), this, - SLOT(onCameraStandToggleClicked(int))); + if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + m_cameraStandToggle->hide(); + else + ret = ret && connect(m_cameraStandToggle, SIGNAL(stateChanged(int)), this, + SLOT(onCameraStandToggleClicked(int))); assert(ret); @@ -3122,6 +3128,8 @@ void FxSchematicColumnNode::onRenderToggleClicked(bool toggled) { TXshColumn *column = fxScene->getXsheet()->getColumn(m_columnIndex); if (column) { column->setPreviewVisible(toggled); + if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + column->setCamstandVisible(toggled); emit sceneChanged(); emit xsheetChanged(); } diff --git a/toonz/sources/toonzqt/paletteviewergui.cpp b/toonz/sources/toonzqt/paletteviewergui.cpp index 1a992f6..3c934ab 100644 --- a/toonz/sources/toonzqt/paletteviewergui.cpp +++ b/toonz/sources/toonzqt/paletteviewergui.cpp @@ -542,7 +542,10 @@ void PageViewer::drawToggleLink(QPainter &p, QRect &chipRect, p.setPen(Qt::black); p.drawRect(rect); - if (globalName[0] == L'+') { + if (style->getOriginalName().empty()) { + p.setBrush(Qt::black); + p.drawRect(rect.adjusted(2, 2, -2, -2)); + } else if (globalName[0] == L'+') { QPointF a(x + 2, y + 2); QPointF b(x + 2, y + 5); QPointF c(x + 5, y + 2); @@ -589,6 +592,8 @@ void PageViewer::paintEvent(QPaintEvent *e) { TPalette *palette = (m_page) ? m_page->getPalette() : 0; if (!palette) return; + bool isStudioPalette = palette->getGlobalName() != L""; + // [i0,i1] = visible cell range QRect visibleRect = e->rect(); int i0 = posToIndex(visibleRect.topLeft()); @@ -648,7 +653,7 @@ void PageViewer::paintEvent(QPaintEvent *e) { } // toggle link - drawToggleLink(p, chipRect, m_page->getStyle(i)); + drawToggleLink(p, chipRect, style); } if (ShowNewStyleButton && !m_page->getPalette()->isLocked()) { int j = getChipCount(); @@ -1173,18 +1178,18 @@ void PageViewer::contextMenuEvent(QContextMenuEvent *event) { bool isLocked = m_page ? m_page->getPalette()->isLocked() : false; // remove links from studio palette - if (m_viewType == LEVEL_PALETTE && m_styleSelection && - !m_styleSelection->isEmpty() && !isLocked && + if (m_styleSelection && !m_styleSelection->isEmpty() && !isLocked && m_styleSelection->hasLinkedStyle()) { - menu.addSeparator(); - QAction *toggleStyleLink = cmd->getAction("MI_ToggleLinkToStudioPalette"); - menu.addAction(toggleStyleLink); - QAction *removeStyleLink = - cmd->getAction("MI_RemoveReferenceToStudioPalette"); - menu.addAction(removeStyleLink); - QAction *getBackOriginalAct = - cmd->getAction("MI_GetColorFromStudioPalette"); - menu.addAction(getBackOriginalAct); + if (m_viewType == LEVEL_PALETTE) { + menu.addSeparator(); + menu.addAction(cmd->getAction("MI_ToggleLinkToStudioPalette")); + menu.addAction(cmd->getAction("MI_RemoveReferenceToStudioPalette")); + menu.addAction(cmd->getAction("MI_GetColorFromStudioPalette")); + } else if (m_viewType == STUDIO_PALETTE) { + menu.addSeparator(); + menu.addAction(cmd->getAction("MI_RemoveReferenceToStudioPalette")); + menu.addAction(cmd->getAction("MI_GetColorFromStudioPalette")); + } } if (((indexPage == 0 && index > 0) || (indexPage > 0 && index >= 0)) && diff --git a/toonz/sources/toonzqt/paramfield.cpp b/toonz/sources/toonzqt/paramfield.cpp index f119c45..d8ae05f 100644 --- a/toonz/sources/toonzqt/paramfield.cpp +++ b/toonz/sources/toonzqt/paramfield.cpp @@ -9,6 +9,7 @@ #include "toonzqt/doublepairfield.h" #include "toonzqt/tonecurvefield.h" #include "toonzqt/checkbox.h" +#include "toonzqt/menubarcommand.h" #include "tdoubleparam.h" #include "tnotanimatableparam.h" @@ -1563,6 +1564,9 @@ void IntParamField::update(int frame) { namespace component { +MyTextEdit::MyTextEdit(const QString &text, QWidget *parent) + : QTextEdit(text, parent) {} + void MyTextEdit::keyPressEvent(QKeyEvent *event) { QTextEdit::keyPressEvent(event); if (event->key() == Qt::Key_Return) emit edited(); @@ -1572,6 +1576,7 @@ void MyTextEdit::focusOutEvent(QFocusEvent *event) { QTextEdit::focusOutEvent(event); emit edited(); } + }; // namespace component StringParamField::StringParamField(QWidget *parent, QString name, diff --git a/toonz/sources/toonzqt/stageschematicnode.cpp b/toonz/sources/toonzqt/stageschematicnode.cpp index 92336be..3eb1a5a 100644 --- a/toonz/sources/toonzqt/stageschematicnode.cpp +++ b/toonz/sources/toonzqt/stageschematicnode.cpp @@ -1753,7 +1753,8 @@ StageSchematicColumnNode::StageSchematicColumnNode(StageSchematicScene *scene, if (levelType == PLT_XSHLEVEL) { m_resizeItem->hide(); m_cameraStandToggle->hide(); - } + } else if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + m_cameraStandToggle->hide(); } //-------------------------------------------------------- @@ -1961,6 +1962,8 @@ void StageSchematicColumnNode::onRenderToggleClicked(bool isActive) { stageScene->getXsheet()->getColumn(m_stageObject->getId().getIndex()); if (column) { column->setPreviewVisible(isActive); + if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) + column->setCamstandVisible(isActive); emit sceneChanged(); emit xsheetChanged(); } diff --git a/toonz/sources/toonzqt/styleselection.cpp b/toonz/sources/toonzqt/styleselection.cpp index 5930e93..fa6ed8f 100644 --- a/toonz/sources/toonzqt/styleselection.cpp +++ b/toonz/sources/toonzqt/styleselection.cpp @@ -499,14 +499,14 @@ void TStyleSelection::enableCommands() { enableCommand(this, MI_PasteNames, &TStyleSelection::pasteStylesName); // available only for level palette - if (m_paletteHandle->getPalette()->getGlobalName() == L"") { - enableCommand(this, MI_GetColorFromStudioPalette, - &TStyleSelection::getBackOriginalStyle); + if (m_paletteHandle->getPalette()->getGlobalName().empty()) { enableCommand(this, MI_ToggleLinkToStudioPalette, &TStyleSelection::toggleLink); - enableCommand(this, MI_RemoveReferenceToStudioPalette, - &TStyleSelection::removeLink); } + enableCommand(this, MI_GetColorFromStudioPalette, + &TStyleSelection::getBackOriginalStyle); + enableCommand(this, MI_RemoveReferenceToStudioPalette, + &TStyleSelection::removeLink); } enableCommand(this, MI_Clear, &TStyleSelection::deleteStyles); enableCommand(this, MI_EraseUnusedStyles, &TStyleSelection::eraseUnusedStyle); @@ -1579,11 +1579,13 @@ class UndoRemoveLink final : public TUndo { bool m_oldEdittedFlag; }; std::vector m_styles; + bool m_isStudioPalette; public: UndoRemoveLink(TPaletteHandle *paletteHandle, int pageIndex) : m_paletteHandle(paletteHandle), m_pageIndex(pageIndex) { - m_palette = m_paletteHandle->getPalette(); + m_palette = m_paletteHandle->getPalette(); + m_isStudioPalette = !m_palette->getGlobalName().empty(); } ~UndoRemoveLink() {} @@ -1618,7 +1620,13 @@ public: for (i = 0; i < (int)m_styles.size(); i++) { ColorStyleData data = m_styles[i]; TColorStyle *cs = page->getStyle(data.m_indexInPage); - cs->setGlobalName(L""); + if (m_isStudioPalette) { + int styleId = page->getStyleId(m_styles[i].m_indexInPage); + std::wstring gname = + L"-" + m_palette->getGlobalName() + L"-" + std::to_wstring(styleId); + cs->setGlobalName(gname); + } else + cs->setGlobalName(L""); cs->setOriginalName(L""); cs->setIsEditedFlag(false); } @@ -1628,7 +1636,7 @@ public: int getSize() const override { return sizeof(*this); } QString getHistoryString() override { - return QObject::tr("Remove Reference in Palette : %1") + return QObject::tr("Remove Reference in Palette : %1") .arg(QString::fromStdWString(m_palette->getPaletteName())); } int getHistoryType() override { return HistoryType::Palette; } @@ -1636,7 +1644,9 @@ public: //----------------------------------------------------------------------------- /*! remove link from studio palette. Delete the global and the original names. - * return true if something changed + * return true if something changed. + * If the target palette is the studio palette, set the global name and make + * the styles "link parent". */ void TStyleSelection::removeLink() { TPalette *palette = getPalette(); @@ -1648,6 +1658,7 @@ void TStyleSelection::removeLink() { assert(page); bool somethingChanged = false; + bool isStudioPalette = !palette->getGlobalName().empty(); UndoRemoveLink *undo = new UndoRemoveLink(m_paletteHandle, m_pageIndex); @@ -1656,7 +1667,17 @@ void TStyleSelection::removeLink() { TColorStyle *cs = page->getStyle(*it); assert(cs); - if (cs->getGlobalName() != L"" || cs->getOriginalName() != L"") { + if (isStudioPalette && !cs->getOriginalName().empty()) { + undo->setColorStyle(*it, cs); + int styleId = page->getStyleId(*it); + std::wstring gname = + L"-" + palette->getGlobalName() + L"-" + std::to_wstring(styleId); + cs->setGlobalName(gname); + cs->setOriginalName(L""); + cs->setIsEditedFlag(false); + somethingChanged = true; + } else if (!isStudioPalette && + (cs->getGlobalName() != L"" || cs->getOriginalName() != L"")) { undo->setColorStyle(*it, cs); cs->setGlobalName(L""); @@ -1780,6 +1801,8 @@ void TStyleSelection::getBackOriginalStyle() { // if the style has no link if (gname == L"") continue; + // if the style is link parent + if (cs->getOriginalName().empty()) continue; // Find the palette from the table int k = gname.find_first_of(L'-', 1); @@ -1834,7 +1857,8 @@ void TStyleSelection::getBackOriginalStyle() { } //----------------------------------------------------------------------------- -/*! return true if there is at least one linked style in the selection +/*! return true if there is at least one linked style in the selection. + link parent styles are not counted */ bool TStyleSelection::hasLinkedStyle() { @@ -1845,13 +1869,18 @@ bool TStyleSelection::hasLinkedStyle() { TPalette::Page *page = palette->getPage(m_pageIndex); assert(page); + bool isStudioPalette = palette->getGlobalName() != L""; + // for each selected style for (std::set::iterator it = m_styleIndicesInPage.begin(); it != m_styleIndicesInPage.end(); ++it) { TColorStyle *cs = page->getStyle(*it); std::wstring gname = cs->getGlobalName(); // if the style has link, return true - if (gname != L"" && (gname[0] == L'-' || gname[0] == L'+')) return true; + if (!gname.empty() && (gname[0] == L'+' || gname[0] == L'-') && + !cs->getOriginalName().empty()) { + return true; + } } return false; } diff --git a/toonz/sources/xdg-data/io.github.OpenToonz.appdata.xml b/toonz/sources/xdg-data/io.github.OpenToonz.appdata.xml index 56e78ed..4f631a7 100644 --- a/toonz/sources/xdg-data/io.github.OpenToonz.appdata.xml +++ b/toonz/sources/xdg-data/io.github.OpenToonz.appdata.xml @@ -28,6 +28,6 @@ - +