diff --git a/.gitignore b/.gitignore index b1cd1d0..7d97f86 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ GeneratedFiles *.suo *.user build* +Thumbs.db # bundled thirdparty libraries /thirdparty/lzo diff --git a/.travis.yml b/.travis.yml index 88b6f3c..17cd93a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,22 @@ language: cpp + +git: + depth: 1 + sudo: required dist: trusty + install: - - if [[ $TRAVIS_OS_NAME == "osx" ]]; then bash ci-scripts/osx/travis-install.sh; fi - - if [[ $TRAVIS_OS_NAME == "linux" ]]; then bash ci-scripts/linux/travis-install.sh; fi + - bash ci-scripts/$TRAVIS_OS_NAME/travis-install.sh script: - - if [[ $TRAVIS_OS_NAME == "osx" ]]; then bash ci-scripts/osx/travis-build.sh; fi - - if [[ $TRAVIS_OS_NAME == "linux" ]]; then bash ci-scripts/linux/travis-build.sh; fi + - bash ci-scripts/$TRAVIS_OS_NAME/travis-build.sh matrix: include: - os: linux compiler: gcc + cache: ccache - os: linux compiler: clang - os: osx + osx_image: xcode8.3 diff --git a/appveyor.yml b/appveyor.yml index 2b03c64..395c875 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.2.0.{build} +version: 1.2.1.{build} pull_requests: do_not_increment_build_number: true skip_tags: true @@ -33,7 +33,7 @@ build: verbosity: minimal after_build: - cmd: >- - C:\Qt\5.9\msvc2015_64\bin\windeployqt.exe %CONFIGURATION%\OpenToonz_1.2.exe + C:\Qt\5.9\msvc2015_64\bin\windeployqt.exe %CONFIGURATION%\OpenToonz.exe copy /Y ..\..\thirdparty\glut\3.7.6\lib\glut64.dll %CONFIGURATION% @@ -48,5 +48,5 @@ after_build: copy /Y ..\..\thirdparty\libmypaint\dist\64\libmypaint-1-4-0.dll %CONFIGURATION% artifacts: - path: toonz\$(PLATFORM)\$(CONFIGURATION) - name: OpenToonz_1.2 + name: OpenToonz diff --git a/ci-scripts/osx/travis-build.sh b/ci-scripts/osx/travis-build.sh index e619b48..7fb8b47 100644 --- a/ci-scripts/osx/travis-build.sh +++ b/ci-scripts/osx/travis-build.sh @@ -4,7 +4,7 @@ pushd thirdparty/tiff-4.0.3 popd cd toonz && mkdir build && cd build cmake ../sources \ - -DQT_PATH=/usr/local/Cellar/qt/5.11.1/lib/ \ + -DQT_PATH=/usr/local/Cellar/qt/5.12.0/lib/ \ -DTIFF_INCLUDE_DIR=../../thirdparty/tiff-4.0.3/libtiff/ \ -DSUPERLU_INCLUDE_DIR=../../thirdparty/superlu/SuperLU_4.1/include/ make -j 2 diff --git a/doc/Thumbs.db b/doc/Thumbs.db deleted file mode 100644 index 912b376..0000000 Binary files a/doc/Thumbs.db and /dev/null differ diff --git a/doc/how_to_build_linux.md b/doc/how_to_build_linux.md index 5b004ea..3875b22 100644 --- a/doc/how_to_build_linux.md +++ b/doc/how_to_build_linux.md @@ -171,7 +171,7 @@ If you need to debug the application, you should be able to use `cmake -DCMAKE_B You can now run the application: ``` -$ LD_LIBRARY_PATH=./lib/opentoonz:$LD_LIBRARY_PATH ./bin/OpenToonz_1.2 +$ LD_LIBRARY_PATH=./lib/opentoonz:$LD_LIBRARY_PATH ./bin/OpenToonz ``` ### Performing a System Installation diff --git a/doc/how_to_build_macosx.md b/doc/how_to_build_macosx.md index 1f443eb..591d4c8 100644 --- a/doc/how_to_build_macosx.md +++ b/doc/how_to_build_macosx.md @@ -39,10 +39,10 @@ git lfs pull ### (Optional) Create the stuff Directory -If the directory `/Applications/OpenToonz/OpenToonz_1.2_stuff` does not exist, enter the following command: +If the directory `/Applications/OpenToonz/OpenToonz_stuff` does not exist, enter the following command: ``` -$ sudo cp -r stuff /Applications/OpenToonz/OpenToonz_1.2_stuff +$ sudo cp -r stuff /Applications/OpenToonz/OpenToonz_stuff ``` ### 3. Build tiff in thirdparty @@ -86,5 +86,5 @@ Please be patient as the install will take a while. ### After Building ``` -$ open ./toonz/OpenToonz_1.2.app +$ open ./toonz/OpenToonz.app ``` diff --git a/doc/how_to_build_macosx_ja.md b/doc/how_to_build_macosx_ja.md index f0f1ad6..3df0f22 100644 --- a/doc/how_to_build_macosx_ja.md +++ b/doc/how_to_build_macosx_ja.md @@ -29,10 +29,10 @@ $ git clone https://github.com/opentoonz/opentoonz ### stuff ディレクトリの設置 (任意) -`/Applications/OpenToonz/OpenToonz_1.2_stuff` というディレクトリが存在していない場合は以下のコマンド等でリポジトリのひな形を設置する必要があります。 +`/Applications/OpenToonz/OpenToonz_stuff` というディレクトリが存在していない場合は以下のコマンド等でリポジトリのひな形を設置する必要があります。 ``` -$ sudo cp -r opentoonz/stuff /Applications/OpenToonz/OpenToonz_1.2_stuff +$ sudo cp -r opentoonz/stuff /Applications/OpenToonz/OpenToonz_stuff ``` ### thirdparty 下の tiff をビルド @@ -67,5 +67,5 @@ $ make ### 完成 ``` -$ open ./toonz/OpenToonz_1.2.app +$ open ./toonz/OpenToonz.app ``` diff --git a/doc/how_to_build_win.md b/doc/how_to_build_win.md index fa00eb0..fd29505 100644 --- a/doc/how_to_build_win.md +++ b/doc/how_to_build_win.md @@ -74,8 +74,8 @@ Rename the following files: ### Setting Up the Program's Path 1. Copy the entire contents of `$opentoonz/toonz/build/Release` to an appropriate folder. -2. Open a Command Prompt and navigate to `QT_DIR/msvc2015_64/bin`. Run the Qt program `windeployqt.exe` with the path for `OpenToonz_1.2.exe` as an argument. - - The necessary Qt library files should be in the same folder as `OpenToonz_1.2.exe` +2. Open a Command Prompt and navigate to `QT_DIR/msvc2015_64/bin`. Run the Qt program `windeployqt.exe` with the path for `OpenToonz.exe` as an argument. + - The necessary Qt library files should be in the same folder as `OpenToonz.exe` - These include: - `Qt5Core.dll` - `Qt5Gui.dll` @@ -86,7 +86,7 @@ Rename the following files: - `Qt5Svg.dll` - `Qt5Widgets.dll` - `Qt5Multimedia.dll` - - These files should be in the corresponding folders in the same folder `OpenToonz_1.2.exe` + - These files should be in the corresponding folders in the same folder `OpenToonz.exe` - `/bearer/qgenericbearer.dll` - `/bearer/qnativewifibearer.dll` - `/iconengines/qsvgicon.dll` @@ -102,11 +102,11 @@ Rename the following files: - `/imageformats/qwebp.dll` - `/platforms/qwindows.dll` -3. Copy the following files to the same folder as `OpenToonz_1.2.exe` +3. Copy the following files to the same folder as `OpenToonz.exe` - `$opentoonz/thirdparty/glut/3.7.6/lib/glut64.dll` - `$opentoonz/thirdparty/glew/glew-1.9.0/bin/64bit/glew32.dll` -4. Copy the `srv` folder from the previous OpenToonz installation to the same folder as `OpenToonz_1.2.exe` +4. Copy the `srv` folder from the previous OpenToonz installation to the same folder as `OpenToonz.exe` - If there is no `srv` folder, OpenToonz can still be used. However, various file formats such as `mov` cannot be used. - Creating the files for `srv` is discussed later. @@ -117,13 +117,13 @@ If a previous binary of OpenToonz was already installed, this step and the follo ### Creating Registry Keys 1. Using the registry editor, create the following key and copy the path of the `$opentoonz/stuff` folder from above to it. - - HKEY_LOCAL_MACHINE\SOFTWARE\OpenToonz\OpenToonz\1.2\TOONZROOT + - HKEY_LOCAL_MACHINE\SOFTWARE\OpenToonz\OpenToonz\TOONZROOT ### Running -`OpenToonz_1.2.exe` can now be run. Congratulations! +`OpenToonz.exe` can now be run. Congratulations! ## Debugging -1. In the Solution Explorer, select the OpenToonz_1.2 project within the OpenToonz solution. +1. In the Solution Explorer, select the OpenToonz project within the OpenToonz solution. 2. In the Project menu, choose Set as StartUp Project. ## Creating the Files for the `srv` Folder diff --git a/doc/how_to_build_win_ja.md b/doc/how_to_build_win_ja.md index 0214fd4..6985438 100644 --- a/doc/how_to_build_win_ja.md +++ b/doc/how_to_build_win_ja.md @@ -64,12 +64,12 @@ Visual Studio 2015 と Qt 5.9 でビルドできることを確認していま ## 実行 ### 実行可能ファイルなどの配置 1. `$oepntoonz/toonz/build/Release` の中身を適当なフォルダにコピーします -2. `OpenToonz_1.2.exe` のパスを引数にして Qt に付属の `windeployqt.exe` を実行します - - 必要な Qt のライブラリなどが `OpenToonz_1.2.exe` と同じフォルダに集められます -3. 下記のファイルを `OpenToonz_1.2.exe` と同じフォルダにコピーします +2. `OpenToonz.exe` のパスを引数にして Qt に付属の `windeployqt.exe` を実行します + - 必要な Qt のライブラリなどが `OpenToonz.exe` と同じフォルダに集められます +3. 下記のファイルを `OpenToonz.exe` と同じフォルダにコピーします - `$opentoonz/thirdparty/glut/3.7.6/lib/glut64.dll` - `$opentoonz/thirdparty/glew/glew-1.9.0/bin/64bit/glew32.dll` -4. バイナリ版の OpenToonz のインストール先にある `srv` フォルダを `OpenToonz_1.2.exe` と同じフォルダにコピーします +4. バイナリ版の OpenToonz のインストール先にある `srv` フォルダを `OpenToonz.exe` と同じフォルダにコピーします - `srv` が無くても OpenToonz は動作しますが、 mov 形式などに対応できません - `srv` 内のファイルの生成方法は後述します @@ -80,10 +80,10 @@ Visual Studio 2015 と Qt 5.9 でビルドできることを確認していま ### レジストリキーの作成 1. レジストリエディタで下記のキーを作成し、 Stuff フォルダの作成でコピーした stuff フォルダのパスを記載します - - HKEY_LOCAL_MACHINE\SOFTWARE\OpenToonz\OpenToonz\1.2\TOONZROOT + - HKEY_LOCAL_MACHINE\SOFTWARE\OpenToonz\OpenToonz\TOONZROOT ### 実行 -OpenToonz_1.2.exe を実行して動作すれば成功です。おめでとうございます。 +OpenToonz.exe を実行して動作すれば成功です。おめでとうございます。 ## `srv` フォルダ内のファイルの生成 OpenToonz は QuickTime SDK を用いて mov 形式などへ対応しています。 QuickTime SDK は 32 ビット版しかないため、 `t32bitsrv.exe` という 32 ビット版の実行可能ファイルにQuickTime SDKを組み込み、64ビット版の OpenToonz は `t32bitsrv.exe` を経由して QuickTime SDK の機能を使用しています。以下の手順では `t32bitsrv.exe` などと合わせて、 32 ビット版の OpenToonz も生成されます。 diff --git a/stuff/config/current.txt b/stuff/config/current.txt index 62c5c93..19e32cf 100644 --- a/stuff/config/current.txt +++ b/stuff/config/current.txt @@ -1255,6 +1255,19 @@ "STD_iwa_BarrelDistortFx.vignetteMidpoint" "Vignetting Midpoint" "STD_iwa_BarrelDistortFx.scale" "Scale" + "STD_iwa_TextFx" "Text Iwa" + "STD_iwa_TextFx.targetType" "Source" + "STD_iwa_TextFx.columnIndex" "Column Index" + "STD_iwa_TextFx.hAlign" "Holizontal Align" + "STD_iwa_TextFx.text" "Text" + "STD_iwa_TextFx.center" "Center" + "STD_iwa_TextFx.width" "Width" + "STD_iwa_TextFx.height" "Height" + "STD_iwa_TextFx.font" "Font" + "STD_iwa_TextFx.textColor" "Text Color" + "STD_iwa_TextFx.boxColor" "Box Color" + "STD_iwa_TextFx.showBorder" "Show Border" + STD_iwa_TiledParticlesFx "Tiled Particles Iwa" diff --git "a/stuff/config/loc/\346\227\245\346\234\254\350\252\236/tnztools.qm" "b/stuff/config/loc/\346\227\245\346\234\254\350\252\236/tnztools.qm" index 521d912..69617a9 100644 Binary files "a/stuff/config/loc/\346\227\245\346\234\254\350\252\236/tnztools.qm" and "b/stuff/config/loc/\346\227\245\346\234\254\350\252\236/tnztools.qm" differ diff --git "a/stuff/config/loc/\346\227\245\346\234\254\350\252\236/toonz.qm" "b/stuff/config/loc/\346\227\245\346\234\254\350\252\236/toonz.qm" index bd2af12..5786124 100644 Binary files "a/stuff/config/loc/\346\227\245\346\234\254\350\252\236/toonz.qm" and "b/stuff/config/loc/\346\227\245\346\234\254\350\252\236/toonz.qm" differ diff --git "a/stuff/config/loc/\346\227\245\346\234\254\350\252\236/toonzqt.qm" "b/stuff/config/loc/\346\227\245\346\234\254\350\252\236/toonzqt.qm" index aaa2b50..a28868f 100644 Binary files "a/stuff/config/loc/\346\227\245\346\234\254\350\252\236/toonzqt.qm" and "b/stuff/config/loc/\346\227\245\346\234\254\350\252\236/toonzqt.qm" differ diff --git a/stuff/config/qss/Blue/Blue.qss b/stuff/config/qss/Blue/Blue.qss index a5127ec..916b68d 100644 --- a/stuff/config/qss/Blue/Blue.qss +++ b/stuff/config/qss/Blue/Blue.qss @@ -1 +1 @@ -.button-show,#LoadLevelShowButton,#CleanupSettingsShowButton,#OutputSettingsShowButton,#FxSettingsPreviewShowButton{image:url('../Default/imgs/white/plus.svg');image-position:center center;margin:0;padding:1;min-width:10;min-height:10}.button-show:checked,#LoadLevelShowButton:checked,#CleanupSettingsShowButton:checked,#OutputSettingsShowButton:checked,#FxSettingsPreviewShowButton:checked{background-color:#2b2c2d;border-color:#262728;image:url('../Default/imgs/white/minus.svg')}.button-show:checked:pressed,#LoadLevelShowButton:checked:pressed,#CleanupSettingsShowButton:checked:pressed,#OutputSettingsShowButton:checked:pressed,#FxSettingsPreviewShowButton:checked:pressed{background-color:#2b2c2d;border-color:#262728}.button-show:checked:hover,#LoadLevelShowButton:checked:hover,#CleanupSettingsShowButton:checked:hover,#OutputSettingsShowButton:checked:hover,#FxSettingsPreviewShowButton:checked:hover{background-color:#303133}.button-tool,QToolButton,#CameraSettingsRadioButton::indicator,#ForceSquaredPixelButton,#SchematicBottomFrame QToolBar QToolButton,#EditToolLockButton::indicator,#flipCustomize{background-color:rgba(255,255,255,0);border:1 solid rgba(255,255,255,0);border-radius:2;color:#e4e5e9;margin:1;padding:0}.button-tool:hover,QToolButton:hover,#CameraSettingsRadioButton::indicator:hover,#ForceSquaredPixelButton:hover,#colorSliderAddButton:hover,#colorSliderSubButton:hover,#SchematicBottomFrame QToolBar QToolButton:hover,#EditToolLockButton::indicator:hover,#flipCustomize:hover{background-color:#6e7174;border-color:#6e7174;color:#e4e5e9}.button-tool:pressed,QToolButton:pressed,#CameraSettingsRadioButton::indicator:pressed,#ForceSquaredPixelButton:pressed,#colorSliderAddButton:pressed,#colorSliderSubButton:pressed,#SchematicBottomFrame QToolBar QToolButton:pressed,#EditToolLockButton::indicator:pressed,#flipCustomize:pressed{background-color:#2b2c2d;border-color:#262728;color:#e4e5e9}.button-tool:checked,QToolButton:checked,#CameraSettingsRadioButton::indicator:checked,#ForceSquaredPixelButton:checked,#SchematicBottomFrame QToolBar QToolButton:checked,#EditToolLockButton::indicator:checked,#flipCustomize:checked{background-color:#5385a6;border-color:#5385a6;color:#fff}.button-tool:checked:hover,QToolButton:checked:hover,#CameraSettingsRadioButton::indicator:checked:hover,#ForceSquaredPixelButton:checked:hover,#SchematicBottomFrame QToolBar QToolButton:checked:hover,#EditToolLockButton::indicator:checked:hover,#flipCustomize:checked:hover{background-color:#6c98b6;border-color:#6c98b6}.button-tool:disabled,QToolButton:disabled,#CameraSettingsRadioButton::indicator:disabled,#ForceSquaredPixelButton:disabled,#SchematicBottomFrame QToolBar QToolButton:disabled,#EditToolLockButton::indicator:disabled,#flipCustomize:disabled{color:#808080}.button-flat,PaletteViewer QToolBar QToolButton{background-color:none;border:0;border-radius:0;margin:0}.button-flat:hover,PaletteViewer QToolBar QToolButton:hover{background-color:#6e7174}.button-flat:pressed,PaletteViewer QToolBar QToolButton:pressed{background-color:#212223}.frame,.GroupBox,#LoadLevelFrame,#PsdSettingsGroupBox,#CleanupSettingsFrame,#OutputSettingsBox,#OutputSettingsCameraBox,#SolidLineFrame,#FunctionParametersPanel,QGroupBox{border:1 solid #212223;border-radius:2}.tab-container,#TabBarContainer{background-color:transparent;qproperty-BottomAboveLineColor:#323435;qproperty-BottomBelowLineColor:#212223}.tab-flat,#StyleEditorTabBar::tab,#PaletteTabBar::tab,#FxSettingsTabBar::tab{background-color:#323435;border-right:1 solid #212223;border-bottom:1 solid #212223;color:#94969a;padding:3 4 3 4}.tab-flat:hover,#StyleEditorTabBar::tab:hover,#PaletteTabBar::tab:hover,#FxSettingsTabBar::tab:hover{background-color:#414345;color:#94969a}.tab-flat:selected,#StyleEditorTabBar::tab:selected,#PaletteTabBar::tab:selected,#FxSettingsTabBar::tab:selected{background-color:#414345;color:#fff;border-bottom-color:#414345}.tab-flat:only-one,#StyleEditorTabBar::tab:only-one,#PaletteTabBar::tab:only-one,#FxSettingsTabBar::tab:only-one{margin:0}.tab-round{background-color:#323435;border-top:1 solid #212223;border-right:1 solid #212223;border-left:1 solid #212223;border-bottom:1 solid #212223;color:#94969a;margin:3 -1 0 0;padding:2 7 1 7}.tab-round:hover{background-color:#414345;color:#94969a}.tab-round:selected{background-color:#414345;border-top-right-radius:2;border-top-left-radius:2;border-bottom-color:#414345;color:#fff;margin:1 -1 -1 0;padding:2 7 2 7}.tab-round:only-one{margin:1 0 0 0;padding:3 7 3 7}.tab-round:last{margin-right:0;border-top-right-radius:2}.tab-round:first{border-top-left-radius:2}QWidget{background-color:#414345;color:#d6d8dd}QWidget:disabled{color:#808080}QFrame{border:0;margin:0;padding:0}QToolTip,#helpToolTip{background-color:#fff;border:1 solid #000;color:#000;padding:1 1}#DockSeparator,QMainWindow::separator,QSplitter::handle{background-color:#141516;height:4;width:4}#TDockPlaceholder{background-color:#F77272}TPanel{background-color:#141516}#TopBar{background:#414345;border:0;border-bottom:1 solid #212223;height:21}#TopBar #EditToolLockButton{background:#414345;spacing:0}#TopBar #EditToolLockButton::indicator{background:none;border:none;height:18;margin:1 2 0 0;padding-left:0;padding-right:0}#TopBarTabContainer{background-color:#414345;margin-bottom:1}#StackedMenuBar{border:0;margin:0;padding:0}QMenuBar{background-color:#414345;border:0}QMenuBar::item{background-color:#414345;border-left:1 solid #414345;margin:0;padding:3 5}QMenuBar::item:selected{background-color:rgba(255,255,255,0.15);color:#d6d8dd}QMenuBar::item:pressed{background-color:#5385a6;color:#fff}#TopBarTab{margin:0;padding:0}#TopBarTab::tab{background-color:#323435;border-top:1 solid #212223;border-right:1 solid #212223;color:#94969a;margin:0 0 0 0;padding:2 8 3 8}#TopBarTab::tab:hover{background-color:#414345;color:#94969a}#TopBarTab::tab:selected{background-color:#414345;color:#fff}#TopBarTab::tab:first{border-left:1 solid #212223}#TopBarTab::tab:last{border-right:1 solid #212223}QMenu{background-color:#414345;border:1 solid #212223;padding:2 0}QMenu::item{padding:3 28}QMenu::item:selected{background-color:#5385a6;color:#fff}QMenu::item:checked{color:#d6d8dd}QMenu::item:checked:selected{background-color:#5385a6;color:#fff}QMenu::item:disabled{background:none;color:#808080}QMenu::item:disabled:selected{border-color:transparent}QMenu::separator{border-top:1 solid #212223;height:0;margin:2 0}QMenu::icon{border-radius:2;margin:0 0 0 3;padding:1}QMenu::icon:checked{background-color:#5385a6}QMenu::indicator{margin-left:7}TPanelTitleBar{background-color:#323435;border-color:#212223;border-style:solid;border-width:0 0 1 0;height:20;min-height:20;qproperty-TitleColor:#8c9093;qproperty-ActiveTitleColor:#43AEE5;qproperty-BorderPixmap:url('none');qproperty-ActiveBorderPixmap:url('../Default/imgs/white/none');qproperty-FloatBorderPixmap:url('none');qproperty-FloatActiveBorderPixmap:url('../Default/imgs/white/none')}QAbstractScrollArea::corner{background-color:#2d2f30}QScrollBar{background-color:#2d2f30;border:0}QScrollBar:horizontal{height:16;margin:0}QScrollBar:vertical{margin:0;width:16}QScrollBar::handle{border:1 solid #4b4d50;border-radius:4}QScrollBar::handle:horizontal:hover,QScrollBar::handle:vertical:hover{background-color:#5f6265;border-color:#5f6265}QScrollBar::handle:horizontal:pressed,QScrollBar::handle:vertical:pressed{background-color:#72767a;border-color:#72767a}QScrollBar::handle:horizontal{background-color:#4b4d50;margin:3 16;min-width:20}QScrollBar::handle:vertical{background-color:#4b4d50;margin:16 3;min-height:20}QScrollBar::add-line{subcontrol-origin:margin;border:0}QScrollBar::add-line:horizontal{subcontrol-position:right;background-color:#2d2f30;margin:0;width:16}QScrollBar::add-line:vertical{subcontrol-position:bottom;background-color:#2d2f30;margin:0;height:16}QScrollBar::sub-line{border:0;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{subcontrol-position:left;background-color:#2d2f30;margin:0;width:16}QScrollBar::sub-line:vertical{subcontrol-position:top;background-color:#2d2f30;margin:0;height:16}QScrollBar::up-arrow:vertical{image:url('../Default/imgs/white/scroll-up.svg');image-position:center center}QScrollBar::up-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::down-arrow:vertical{image:url('../Default/imgs/white/scroll-down.svg');image-position:center center}QScrollBar::down-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::left-arrow:horizontal{image:url('../Default/imgs/white/scroll-left.svg');image-position:center center}QScrollBar::left-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::right-arrow:horizontal{image:url('../Default/imgs/white/scroll-right.svg');image-position:center center}QScrollBar::right-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::sub-page:horizontal,QScrollBar::add-page:horizontal,QScrollBar::sub-page:vertical,QScrollBar::add-page:vertical{background:none}QToolBar{padding:0}QToolBar::separator:horizontal{border-left:1 solid #212223;margin:0 1;width:0}QToolBar::separator:vertical{border-top:1 solid #212223;height:0;margin:1 0}QToolBar QLabel{margin-top:1}QToolBar QToolBar{border:0}QToolButton::menu-indicator{image:none}QToolButton::menu-button{border-image:none}.DvScrollWidget QPushButton,DvScrollWidget QPushButton,#ScrollLeftButton QPushButton,#ScrollRightButton QPushButton,#ScrollUpButton QPushButton,#ScrollDownButton QPushButton{background-color:#616467;border:0 solid red;border-radius:0;padding:0;max-width:16}.DvScrollWidget QPushButton:hover,DvScrollWidget QPushButton:hover,#ScrollLeftButton QPushButton:hover,#ScrollRightButton QPushButton:hover,#ScrollUpButton QPushButton:hover,#ScrollDownButton QPushButton:hover{background-color:#6e7174}.DvScrollWidget QPushButton:pressed,DvScrollWidget QPushButton:pressed,#ScrollLeftButton QPushButton:pressed,#ScrollRightButton QPushButton:pressed,#ScrollUpButton QPushButton:pressed,#ScrollDownButton QPushButton:pressed{background-color:#2b2c2d}#ScrollLeftButton,#ScrollRightButton,#ScrollUpButton,#ScrollDownButton{margin:0;min-width:16}#ScrollLeftButton{border-right:1 solid #212223;image:url('../Default/imgs/white/scroll-left.svg')}#ScrollRightButton{border-left:1 solid #212223;margin-left:3;image:url('../Default/imgs/white/scroll-right.svg')}#ScrollUpButton{image:url('../Default/imgs/white/scroll-up.svg')}#ScrollDownButton{image:url('../Default/imgs/white/scroll-down.svg')}#keyFrameNavigator{background:none;margin:0;padding:0}#keyFrameNavigator QToolButton{min-width:18}#keyFrameNavigator #PreviousKey{image:url('../Default/imgs/white/prevkey.svg')}#keyFrameNavigator #PreviousKey:hover{image:url('../Default/imgs/white/prevkey_over.svg')}#keyFrameNavigator #PreviousKey:disabled{image:url('../Default/imgs/white/prevkey_disabled.svg')}#keyFrameNavigator #NextKey{image:url('../Default/imgs/white/nextkey.svg')}#keyFrameNavigator #NextKey:hover{image:url('../Default/imgs/white/nextkey_over.svg')}#keyFrameNavigator #NextKey:disabled{image:url('../Default/imgs/white/nextkey_disabled.svg')}.treeview,QTreeWidget,QTreeView,#FunctionEditorTree{background-color:#2d2f30;alternate-background-color:#323435;border:0;margin:0;outline:0}.treeview::item:selected,QTreeWidget::item:selected,QTreeView::item:selected,#FunctionEditorTree::item:selected{background-color:#5385a6;color:#fff}.treeview::branch:adjoins-item,QTreeWidget::branch:adjoins-item,QTreeView::branch:adjoins-item,#FunctionEditorTree::branch:adjoins-item{border-image:url('')}.treeview::branch:has-siblings,QTreeWidget::branch:has-siblings,QTreeView::branch:has-siblings,#FunctionEditorTree::branch:has-siblings{border-image:url('')}.treeview::branch:has-siblings:adjoins-item,QTreeWidget::branch:has-siblings:adjoins-item,QTreeView::branch:has-siblings:adjoins-item,#FunctionEditorTree::branch:has-siblings:adjoins-item{border-image:url('')}.treeview::branch:has-children:closed,QTreeWidget::branch:has-children:closed,QTreeView::branch:has-children:closed,#FunctionEditorTree::branch:has-children:closed{background:url('../Default/imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:open,QTreeWidget::branch:has-children:open,QTreeView::branch:has-children:open,#FunctionEditorTree::branch:has-children:open{background:url('../Default/imgs/white/treebranch-open.svg') no-repeat;background-position:center center;image:none}.treeview::branch:has-children:has-siblings:closed,QTreeWidget::branch:has-children:has-siblings:closed,QTreeView::branch:has-children:has-siblings:closed,#FunctionEditorTree::branch:has-children:has-siblings:closed{background:url('../Default/imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:has-siblings:open,QTreeWidget::branch:has-children:has-siblings:open,QTreeView::branch:has-children:has-siblings:open,#FunctionEditorTree::branch:has-children:has-siblings:open{background:url('../Default/imgs/white/treebranch-open.svg') no-repeat;background-position:center center;border-image:none;image:none}QListView{outline:0;background:#2d2f30;alternate-background-color:#323435}#TabBarContainer{background-color:#323435}.Button,QPushButton,.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{background-color:#616467;border:1 solid #414345;border-radius:2;color:#e4e5e9;margin:0;padding:3 15}.Button:hover,QPushButton:hover,.ComboBox:hover,#ViewerFpsSlider::sub-line:horizontal:hover,#ViewerFpsSlider::add-line:horizontal:hover,QComboBox:hover{background-color:#6e7174;border-color:#414345;color:#e4e5e9}.Button:pressed,QPushButton:pressed,#ViewerFpsSlider::sub-line:horizontal:pressed,#ViewerFpsSlider::add-line:horizontal:pressed{background-color:#2b2c2d;border-color:#262728;color:#e4e5e9}.Button:checked,QPushButton:checked{background-color:#2b2c2d;border-color:#262728;color:#e4e5e9}.Button:checked:hover,QPushButton:checked:hover{background-color:#303133}.Button:checked:hover:pressed,QPushButton:checked:hover:pressed{background:#2b2c2d}.Button:disabled,QPushButton:disabled,.ComboBox:disabled,#ViewerFpsSlider::sub-line:horizontal:disabled,#ViewerFpsSlider::add-line:horizontal:disabled,QComboBox:disabled{background-color:#4d5052;border-color:#414345;color:#808080}#PushButton_NoPadding{padding:3}.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{padding:1 0 1 4;margin:1 0}.ComboBox::drop-down,QComboBox::drop-down{image:url('../Default/imgs/white/combo_downarrow.svg');image-position:center center;width:16}.ComboBox::drop-down:disabled,QComboBox::drop-down:disabled{image:url('../Default/imgs/white/combo_downarrow_disabled.svg')}.ComboBox QAbstractItemView,QComboBox QAbstractItemView{background-color:#414345;border:1 solid #212223;selection-background-color:#5385a6;selection-color:#fff}.LineEdit,QLineEdit,#TaskSheetItem,#tasksRemoveBox,#tasksAddBox{background-color:#28292b;border:1 solid #262728;border-radius:2;color:#d6d8dd;selection-background-color:#5385a6;selection-color:#fff;padding:0 0 0 1}.LineEdit:focus,QLineEdit:focus,#TaskSheetItem:focus,#tasksRemoveBox:focus,#tasksAddBox:focus{background-color:#28292b;border-color:#5385a6;color:#d6d8dd}.LineEdit:disabled,QLineEdit:disabled,#TaskSheetItem:disabled,#tasksRemoveBox:disabled,#tasksAddBox:disabled{background-color:#353638;border-color:#333537;color:#808080}.CheckBox,QCheckBox{color:#d6d8dd}.CheckBox:hover,QCheckBox:hover,.RadioButton:hover,QRadioButton:hover{color:#fff}.CheckBox:disabled,QCheckBox:disabled{color:#808080}.CheckBox::indicator,QMenu::indicator,QCheckBox::indicator,.GroupBox::indicator,QGroupBox::indicator{background-color:#28292b;border:1 solid #262728;border-radius:2;height:9;padding:1;width:9}.CheckBox::indicator:hover,QMenu::indicator:hover,.CheckBox::indicator:checked:hover,QCheckBox::indicator:hover,.GroupBox::indicator:hover,QMenu::indicator:checked:hover,QCheckBox::indicator:checked:hover,.GroupBox::indicator:checked:hover,QGroupBox::indicator:hover,QGroupBox::indicator:checked:hover{background-color:#28292b;border-color:#5385a6}.CheckBox::indicator:checked,QMenu::indicator:checked,QCheckBox::indicator:checked,.GroupBox::indicator:checked,QGroupBox::indicator:checked{background-color:#28292b;border-color:#262728;image:url('../Default/imgs/white/checkmark.svg')}.CheckBox::indicator:checked:disabled,QMenu::indicator:checked:disabled,QCheckBox::indicator:checked:disabled,.GroupBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled{background-color:#353638;border-color:#353638;image:url('../Default/imgs/white/checkmark_disabled.svg')}.CheckBox::indicator:disabled,QMenu::indicator:disabled,QCheckBox::indicator:disabled,.GroupBox::indicator:disabled,QGroupBox::indicator:disabled{background-color:#353638;border-color:#353638}.RadioButton::indicator:unchecked,QRadioButton::indicator:unchecked,#CameraSettingsRadioButton_Small::indicator:unchecked{image:url('../Default/imgs/white/radiobutton_unchecked.svg');image-position:center center}.RadioButton::indicator:checked,QRadioButton::indicator:checked,#CameraSettingsRadioButton_Small::indicator:checked{image:url('../Default/imgs/white/radiobutton_checked.svg');image-position:center center}.GroupBox,QGroupBox{margin:6 0 0 0;padding:5 0}.GroupBox::title,QGroupBox::title{subcontrol-origin:margin;left:15;margin:-3 0 0 0;padding:0 3}.GroupBox::title:hover,QGroupBox::title:hover{color:#fff}.GroupBox::title:disabled,QGroupBox::title:disabled{color:#808080}.GroupBox::indicator,QGroupBox::indicator{subcontrol-origin:margin;margin-top:2}.GroupBox:disabled,QGroupBox:disabled{color:#808080}.Slider::groove:horizontal,QSlider::groove:horizontal{background-color:transparent;background-image:url('../Default/imgs/white/slider-groove.svg');background-position:center center;background-repeat:repeat-x;margin:0;height:20;min-height:20}.Slider::groove:horizontal:disabled,QSlider::groove:horizontal:disabled{background-image:url('../Default/imgs/white/slider-groove_disabled.svg')}.Slider::handle:horizontal,QSlider::handle:horizontal{width:10;margin:-2 -1;image:url('../Default/imgs/white/slider-handle.svg')}.Slider::handle:horizontal:disabled,QSlider::handle:horizontal:disabled{image:url('../Default/imgs/white/slider-handle_disabled.svg')}#IntPairField,#DoublePairField{qproperty-LightLineColor:#262728;qproperty-LightLineEdgeColor:#262728;qproperty-DarkLineColor:#262728;qproperty-MiddleLineColor:#262728;qproperty-HandleLeftPixmap:url("../Default/imgs/white/slider-handle.svg");qproperty-HandleRightPixmap:url("../Default/imgs/white/slider-handle.svg");qproperty-HandleLeftGrayPixmap:url("../Default/imgs/white/slider-handle_disabled.svg");qproperty-HandleRightGrayPixmap:url("../Default/imgs/white/slider-handle_disabled.svg")}#DirTreeView{background-color:#2d2f30;alternate-background-color:#2d2f30;border:1 solid #212223;border-right:0}DvItemViewerPanel{qproperty-TextColor:#d6d8dd;qproperty-AlternateBackground:#3a3b3d;qproperty-SelectedTextColor:#fff;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedItemBackground:#5385a6}#FileBrowser DvItemViewerPanel,#SceneCast DvItemViewerPanel{background-color:#414345}#FileBrowser #castFrame,#SceneCast #castFrame{border-top:1 solid #212223;border-right:1 solid #212223;border-bottom:1 solid #212223;margin:0}#FileBrowser QToolButton,#SceneCast QToolButton{padding:1}DvDirTreeView{qproperty-TextColor:#d6d8dd;qproperty-SelectedTextColor:#fff;qproperty-SelectedItemBackground:#5385a6;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedFolderTextColor:#fff;alternate-background-color:#323435;background-color:#2d2f30;border:1 solid #212223}#FileDoesNotExistLabel{color:#f00}#SceneCast QToolBar{border-top:1 solid #212223}#SceneCast QToolButton{margin:3 1 2 1;padding:1}#CastBrowser{border:0;margin:0}#FilmStrip QComboBox{border-radius:0;border-width:0}#FilmStrip QComboBox QAbstractItemView{background-color:#414345}#CleanupSettings #CleanupSettingsFrame{margin-top:2;margin-bottom:4}#CleanupSettings QGroupBox{margin-bottom:3}ParamsPage{qproperty-TextColor:#d6d8dd}#CameraSettingsButton{padding:2}#CameraSettingsRadioButton:hover{background:none}#CameraSettingsRadioButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#CameraSettingsRadioButton::indicator:unchecked{image:url('../Default/imgs/white/lock_off.svg')}#CameraSettingsRadioButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('../Default/imgs/white/lock_on.svg')}#CameraSettingsRadioButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#CameraSettingsDPI{color:#9fdaff}#CameraSettingsRadioButton_Small{padding:0}#CameraSettingsRadioButton_Small::indicator{background-color:transparent;border:0;height:21;margin:0;width:11}#ForceSquaredPixelButton{height:16;border:1 solid rgba(255,255,255,0);image:url('../Default/imgs/white/fsp_unchecked.svg');padding:2;width:16;margin:0}#ForceSquaredPixelButton:checked{image:url('../Default/imgs/white/fsp_checked.svg')}#OutputSettingsLabel{color:#9fdaff}PencilTestPopup{min-height:730px;min-width:512px}#MatchLineButton{background-color:#66696c}#MatchLineButton:checked{background-color:#8c9093;border:2 solid #5385a6;border-radius:2}#LargeSizedText{font-size:17}#StartupLabel{padding:3}#StartupLabel:hover{background:#5a5d5f}QStatusBar{background-color:#c0c0c0}QStatusBar::item{border:0}QStatusBar QLabel{background-color:#c0c0c0}QStatusBar #StatusBarLabel{background-color:#fff;padding:1 3}#TitleTxtLabel{color:#9fdaff}#StyleEditor QPushButton{margin:2 1;padding:0}#StyleEditor #TabBarContainer{margin-left:-4}#StyleEditor #bottomWidget{border-top:1 solid #212223;padding:3 2 8 3}#StyleEditor #bottomWidget QPushButton{padding:3 5}#StyleEditorTabBar::tab::first{border-left:1 solid #212223}#HexagonalColorWheel{qproperty-BGColor:#414345}#colorSlider::groove:horizontal{height:1;border-image:none}#colorSlider::handle:horizontal{width:8;margin:-8 -4}#colorSliderAddButton,#colorSliderSubButton{background:none;border-color:transparent;image-position:center center;min-height:16;padding:0;min-width:18}#colorSliderAddButton{image:url('../Default/imgs/white/scroll-right.svg')}#colorSliderSubButton{image:url('../Default/imgs/white/scroll-left.svg')}#PlainColorPageParts{border-bottom:1 solid #212223}#PlainColorPageParts QLineEdit{max-width:35}PaletteViewer DvScrollWidget QPushButton{border-top:0;margin-bottom:1;max-width:15;min-width:15}PaletteViewer DvScrollWidget #ScrollLeftButton{border-radius:0;margin-bottom:1;max-width:16;min-width:16}PaletteViewer DvScrollWidget #ScrollRightButton{border-radius:0;margin-left:1;margin-bottom:1;max-width:16;min-width:16}PaletteViewer QToolBar{background:none;border-bottom:1 solid #212223;padding:0;margin:0}PaletteViewer QToolBar::separator:horizontal{margin:0}PaletteViewer QToolBar QToolButton{margin:0 0 1 0;padding:1 0 2 0}#PageViewer{qproperty-TextColor:#d6d8dd}#PaletteLockButton{border-radius:0;margin:0 0 1 1}#PaletteLockButton:checked{background-color:#C34040;border-color:#C34040}#PaletteLockButton:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#WordButton{padding-right:0;padding-left:0}QDialog{background-color:#414345}QDialog #dialogButtonFrame{background-color:#37393a;border-top:1 solid #212223}QDialog #dialogButtonFrame QPushButton{border-color:#37393a;outline:0}QDialog #dialogButtonFrame QPushButton:focus{background-color:#5385a6;border-color:#37393a;color:#fff}QDialog #dialogButtonFrame QPushButton:focus:hover{background-color:#6c98b6}QDialog #dialogButtonFrame QPushButton:focus:pressed{background-color:#2b2c2d;border-color:#262728;color:#e4e5e9}#SceneSettings QLabel{color:#9fdaff}#PreferencesPopup QListWidget{background-color:#2d2f30;alternate-background-color:#2d2f30;border:1 solid #212223;font-size:13}#PreferencesPopup QListWidget::item{border:0;padding:3}#PreferencesPopup QListWidget::item:hover{color:#d6d8dd;background-color:rgba(255,255,255,0.15)}#PreferencesPopup QListWidget::item:selected{background-color:#5385a6;color:#fff}#ShortcutTree{border:1 solid #212223}#ShortcutTree::item{padding:1 0}#ShortcutTree QScrollBar:vertical{width:16;margin-right:-1}ProjectPopup QLabel{color:#9fdaff}#GearButton{qproperty-icon:url('../Default/imgs/white/gear.svg')}#SubfolderButton{qproperty-icon:url('../Default/imgs/white/subfolder.svg')}SchematicViewer{qproperty-TextColor:#d6d8dd;qproperty-VerticalLineColor:#222;qproperty-LevelColumnColor:#4C6E4C;qproperty-VectorColumnColor:#7B7B4C;qproperty-ChildColumnColor:#6A526B;qproperty-FullcolorColumnColor:#657A96;qproperty-FxColumnColor:#56553C;qproperty-PaletteColumnColor:#3A655F;qproperty-MeshColumnColor:#684D86;qproperty-TableColor:#62628c;qproperty-ActiveCameraColor:#2d7dca;qproperty-OtherCameraColor:#6c797b;qproperty-GroupColor:#3b6e9c;qproperty-PegColor:#9f6e3c;qproperty-SplineColor:#6a9d1c;qproperty-ActiveOutputColor:#2d7dca;qproperty-OtherOutputColor:#6c797b;qproperty-XsheetColor:#62628c;qproperty-NormalFxColor:#6a7e96;qproperty-MacroFxColor:#815c79;qproperty-ImageAdjustFxColor:#656287;qproperty-LayerBlendingFxColor:#4f757d;qproperty-MatteFxColor:#ae7171;qproperty-SchematicPreviewButtonBgOnColor:#c8c864;qproperty-SchematicPreviewButtonOnImage:url('../Default/imgs/white/x_prev_eye_on.svg');qproperty-SchematicPreviewButtonBgOffColor:rgba(200,200,100,0.5);qproperty-SchematicPreviewButtonOffImage:url('../Default/imgs/white/x_prev_eye_off.svg');qproperty-SchematicCamstandButtonBgOnColor:#eb906b;qproperty-SchematicCamstandButtonOnImage:url('../Default/imgs/white/x_table_view_on.svg');qproperty-SchematicCamstandButtonTranspImage:url('../Default/imgs/white/x_table_view_transp.svg');qproperty-SchematicCamstandButtonBgOffColor:rgba(235,144,107,0.5);qproperty-SchematicCamstandButtonOffImage:url('../Default/imgs/white/x_table_view_off.svg')}#SchematicBottomFrame{background-color:#414345;border:0;margin:0;padding:0}#SchematicBottomFrame QToolBar::separator:horizontal{margin:0}#SchematicBottomFrame QToolBar QToolButton{padding:0;margin:2}#SchematicSceneViewer{background-color:#353638;border-bottom:1 solid #212223}#FxSettingsTabBar::tab{border-top:1 solid #212223}#FxSettingsTabBar::tab::first,#FxSettingsTabBar::tab::only-one{border-left:1 solid #212223}FxSettings QToolBar{border-top:1 solid #212223;border-right:1 solid #212223;border-left:1 solid #212223;min-height:23;padding:3 0}FxSettings QToolBar QToolBar{border:0}#FxSettingsLabel{color:#a0e680}#FxSettingsHelpButton{background-color:#80a0dc;color:#000;padding-top:0;padding-bottom:0}#FxSettingsHelpButton:hover{background-color:#a8bee7}#ScriptConsole{font-family:'Courier New',monospace;border:0;color:#000000;padding:3}#ScriptConsole QFrame{background-color:#dcdcdc}#ScriptConsole TPanelTitleBar{background-color:#323435}#TaskSheetItemLabel{color:#d6d8dd}#Tasks QToolBar{border-bottom:1 solid #212223;margin:0;padding:0}#Tasks QToolBar QToolButton{margin:2 2 3 2}#ToolBar QToolBar{padding-left:2}#ToolOptions TPanelTitleBar{border-right:1 solid #212223;border-bottom:0}#CommandBar TPanelTitleBar{border-right:1 solid #212223;border-bottom:0}IconViewField{qproperty-ThicknessPixmap:url("../Default/imgs/white/selectiontool_thickness.svg")}#EditToolLockButton{spacing:0}#EditToolLockButton:hover{background:none}#EditToolLockButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#EditToolLockButton::indicator:unchecked{image:url('../Default/imgs/white/lock_off.svg')}#EditToolLockButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('../Default/imgs/white/lock_on.svg')}#EditToolLockButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}PopupButton::menu-indicator{border-left:0;height:17;image:url('../Default/imgs/white/combo_downarrow.svg');width:10}PopupButton::menu-indicator:hover{image:url('../Default/imgs/white/combo_downarrow.svg')}PopupButton::menu-indicator:disabled{image:url('../Default/imgs/white/combo_downarrow_disabled.svg')}#Cap,#Join{padding:0 4 0 -8;max-width:32;min-width:32}#Cap QMenu,#Join QMenu{max-width:28;min-width:28}#Cap QMenu::item,#Join QMenu::item{max-width:28;min-width:28;padding:0}QToolBar#MediumPaddingToolBar QToolButton{padding-left:3;padding-right:3}QToolBar#WidePaddingToolBar QToolButton{padding-left:6;padding-right:6}#CommandBar{margin:0;padding:0;border:0}#CommandBar::separator:horizontal{margin-right:3;margin-left:3}#expandButton:checked{background-color:transparent;border-color:transparent;color:#d6d8dd}#expandButton:checked:hover{background-color:#6e7174;border-color:#6e7174}#expandButton:checked:pressed{background-color:#2b2c2d;border-color:#262728}#ComboViewerPanel Toolbar{border-bottom:1 solid #212223}#ComboViewerPanel Toolbar::separator:horizontal{margin:0 0 0 2}#ComboViewerPanel Toolbar QToolButton{margin:2 0 3 2}#ComboViewerToolOptions{border-bottom:1 solid #212223}#ComboViewer #ToolBarContainer,#ViewerPanel #ToolBarContainer,FlipBook #ToolBarContainer{background-color:transparent;border-top:2 solid #212223;border-bottom:1 solid #212223;padding-right:-1}#flipCustomize{margin-left:3}#flipCustomize::menu-button{background-color:transparent;width:35}#flipCustomize::menu-arrow{image:none}QToolBar#FlipConsolePlayToolBar::separator:horizontal{margin:0 3}QToolBar#FlipConsolePlayToolBar QToolButton{margin-top:2;margin-bottom:2;height:16;padding-left:1;padding-right:1}#ViewerFpsSlider{background-color:transparent;background-image:url('../Default/imgs/white/slider-groove.svg');background-position:center center;background-repeat:repeat-x;border:0;height:19;margin:0 3 0 37;max-width:300;min-width:0}#ViewerFpsSlider::sub-line:horizontal{subcontrol-origin:absolute;background-color:#616467;border:1 solid #414345;border-top-left-radius:2;border-bottom-left-radius:2;height:16;left:-33;width:14}#ViewerFpsSlider::add-line:horizontal{subcontrol-position:left;background-color:#616467;border:1 solid #414345;border-top-right-radius:2;border-bottom-right-radius:2;left:18;height:16;image-position:center center;width:13}#ViewerFpsSlider::handle::horizontal{background-color:#999c9f;border:1 solid #999c9f;border-radius:2;margin:2 0 3 0;min-width:9;width:9;max-width:9}FlipSlider{qproperty-PBHeight:15;qproperty-PBOverlay:url('../Default/imgs/white/flipslider.svg');qproperty-PBColorMarginLeft:1;qproperty-PBColorMarginTop:2;qproperty-PBColorMarginRight:1;qproperty-PBColorMarginBottom:2;qproperty-PBMarker:url('../Default/imgs/white/flipmarker.svg');qproperty-PBMarkerMarginLeft:3;qproperty-PBMarkerMarginRight:3;qproperty-notStartedColor:rgba(205,101,101,0.78);qproperty-startedColor:#1abc3f;qproperty-baseColor:#28292b;qproperty-finishedColor:#28292b}Ruler{qproperty-ParentBGColor:#414345;qproperty-ScaleColor:#d6d8dd}#RulerToolOptionValues{color:#000}#xsheetArea,#ScrollArea{background-color:#2d2f30;border:0}#xsheetScrollArea{border:0}#cornerWidget QToolButton{padding:0}#xsheetColumnAreaMenu_Preview{background-color:#E6E678}#xsheetColumnAreaMenu_Lock{background-color:#F5F5F5}#xsheetColumnAreaMenu_Camstand{background-color:#FFA480}#xsheetColumnAreaMenu_Preview,#xsheetColumnAreaMenu_Lock,#xsheetColumnAreaMenu_Camstand{color:#000}#noteTextEdit{color:#000}XsheetViewer{qproperty-TextColor:#d6d8dd;qproperty-BGColor:#353638;qproperty-LightLineColor:#262728;qproperty-MarkerLineColor:#1E96C4;qproperty-VerticalLineColor:#222;qproperty-VerticalLineHeadColor:#777b7f;qproperty-PreviewFrameTextColor:#9fdaff;qproperty-CurrentRowBgColor:#506082;qproperty-EmptyColumnHeadColor:#5a5d60;qproperty-SelectedColumnTextColor:#E66464;qproperty-EmptyCellColor:#393b3d;qproperty-NotEmptyColumnColor:#414345;qproperty-SelectedEmptyCellColor:#64676a;qproperty-LevelColumnColor:#4C6E4C;qproperty-LevelColumnBorderColor:#8FB38F;qproperty-SelectedLevelColumnColor:#678667;qproperty-VectorColumnColor:#7B7B4C;qproperty-VectorColumnBorderColor:#BBBB9A;qproperty-SelectedVectorColumnColor:#949466;qproperty-ChildColumnColor:#6A526B;qproperty-ChildColumnBorderColor:#B1A3B3;qproperty-SelectedChildColumnColor:#816e82;qproperty-FullcolorColumnColor:#657A96;qproperty-FullcolorColumnBorderColor:#9EB8BB;qproperty-SelectedFullcolorColumnColor:#8895a6;qproperty-FxColumnColor:#56553C;qproperty-FxColumnBorderColor:#95958A;qproperty-SelectedFxColumnColor:#6f6e56;qproperty-ReferenceColumnColor:#616161;qproperty-ReferenceColumnBorderColor:#A2A2A2;qproperty-SelectedReferenceColumnColor:#7a7a7a;qproperty-PaletteColumnColor:#3A655F;qproperty-PaletteColumnBorderColor:#86ACA7;qproperty-SelectedPaletteColumnColor:#52807a;qproperty-MeshColumnColor:#684D86;qproperty-MeshColumnBorderColor:#BA92EF;qproperty-SelectedMeshColumnColor:#82689e;qproperty-SoundTextColumnColor:#c8c8c8;qproperty-SoundTextColumnBorderColor:#8c8c8c;qproperty-SelectedSoundTextColumnColor:#e2e2e2;qproperty-SoundColumnColor:#657456;qproperty-SoundColumnBorderColor:#A0AF7D;qproperty-SelectedSoundColumnColor:#7e8b72;qproperty-SoundColumnHlColor:#34FE5E;qproperty-SoundColumnTrackColor:#B6C29D;qproperty-ColumnHeadPastelizer:#000;qproperty-SelectedColumnHead:#506082;qproperty-LightLightBGColor:#393b3d;qproperty-LightBGColor:#eaebec;qproperty-DarkBGColor:#dbdcdd;qproperty-DarkLineColor:#8e9194;qproperty-XsheetColumnNameBgColor:rgba(0,0,0,0);qproperty-XsheetDragBarHighlightColor:rgba(255,255,255,0.5);qproperty-XsheetPreviewButtonBgOnColor:#c8c864;qproperty-XsheetPreviewButtonOnImage:url('../Default/imgs/white/x_prev_eye_on.svg');qproperty-XsheetPreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetPreviewButtonOffImage:url('../Default/imgs/white/x_prev_eye_off.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');qproperty-XsheetCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetCamstandButtonOffImage:url('../Default/imgs/white/x_table_view_off.svg');qproperty-XsheetLockButtonBgOnColor:rgba(255,255,255,0.3);qproperty-XsheetLockButtonOnImage:url('../Default/imgs/white/x_lock_on.svg');qproperty-XsheetLockButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetLockButtonOffImage:url('../Default/imgs/white/x_lock_off.svg');qproperty-XsheetConfigButtonBgColor:rgba(255,255,255,0);qproperty-XsheetConfigButtonImage:url('../Default/imgs/white/x_config.svg');qproperty-TimelinePreviewButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelinePreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineCamstandButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelineCamstandButtonTranspImage:url('../Default/imgs/white/timeline_toggle_transp.svg');qproperty-TimelineCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineLockButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelineLockButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineConfigButtonBgColor:rgba(255,255,255,0);qproperty-TimelineConfigButtonImage:url('../Default/imgs/white/timeline_config.svg');qproperty-LayerHeaderPreviewImage:url('../Default/imgs/white/layer_header_prev_eye.svg');qproperty-LayerHeaderPreviewOverImage:url('../Default/imgs/white/layer_header_prev_eye_over.svg');qproperty-LayerHeaderCamstandImage:url('../Default/imgs/white/layer_header_table_view.svg');qproperty-LayerHeaderCamstandOverImage:url('../Default/imgs/white/layer_header_table_view_over.svg');qproperty-LayerHeaderLockImage:url('../Default/imgs/white/lock_on.svg');qproperty-LayerHeaderLockOverImage:url('../Default/imgs/white/lock_on_over.svg')}#XSheetToolbar{margin:0;padding:0;border:0}#XSheetToolbar QToolButton{padding:0;margin:4 1;min-height:19;height:19}#XSheetToolbar::separator:horizontal{margin:0 4}#FunctionEditor QToolBar{border-bottom:1 solid #212223}#FunctionEditor QToolBar QToolBar{border:0}#FunctionEditor QToolBar QLabel{margin-left:5}#FunctionEditor QToolBar QToolButton{height:18}#FunctionEditorTree{border-top:1 solid #212223}FunctionTreeView{qproperty-TextColor:#d6d8dd;qproperty-CurrentTextColor:#E66464}FunctionPanel{qproperty-BGColor:#343638;qproperty-ValueLineColor:#28292b;qproperty-FrameLineColor:#28292b;qproperty-OtherCurvesColor:#7f8386;qproperty-RulerBackground:#2d2e30;qproperty-TextColor:#d6d8dd;qproperty-SubColor:#000;qproperty-SelectedColor:#FFA500}SpreadsheetViewer{qproperty-LightLightBGColor:#393b3d;qproperty-CurrentRowBgColor:#506082;qproperty-LightLineColor:#262728;qproperty-MarkerLineColor:#1E96C4;qproperty-BGColor:#414345;qproperty-VerticalLineColor:#222;qproperty-KeyFrameColor:#995d1d;qproperty-KeyFrameBorderColor:#c9b04b;qproperty-SelectedKeyFrameColor:#be772b;qproperty-InBetweenColor:#666250;qproperty-InBetweenBorderColor:#cdcec8;qproperty-SelectedInBetweenColor:#7d7a6c;qproperty-SelectedEmptyColor:#64676a;qproperty-SelectedSceneRangeEmptyColor:#6d7073;qproperty-TextColor:#d6d8dd;qproperty-ColumnHeaderBorderColor:#777b7f;qproperty-SelectedColumnTextColor:#E66464}#ExpressionField{background-color:#e0e1e2;border:1 solid #2d2e2f;margin:0}#FunctionSegmentViewerLinkButton{background-image:url('../Default/imgs/white/segment_unlinked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:hover{background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:checked{background-image:url('../Default/imgs/white/segment_linked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:disabled{background-image:url('../Default/imgs/white/segment_disabled.svg');background-repeat:no-repeat} \ No newline at end of file +.button-show,#LoadLevelShowButton,#CleanupSettingsShowButton,#OutputSettingsShowButton,#FxSettingsPreviewShowButton{image:url('../Default/imgs/white/plus.svg');image-position:center center;margin:0;padding:1;min-width:10;min-height:10}.button-show:checked,#LoadLevelShowButton:checked,#CleanupSettingsShowButton:checked,#OutputSettingsShowButton:checked,#FxSettingsPreviewShowButton:checked{background-color:#2b2c2d;border-color:#262728;image:url('../Default/imgs/white/minus.svg')}.button-show:checked:pressed,#LoadLevelShowButton:checked:pressed,#CleanupSettingsShowButton:checked:pressed,#OutputSettingsShowButton:checked:pressed,#FxSettingsPreviewShowButton:checked:pressed{background-color:#2b2c2d;border-color:#262728}.button-show:checked:hover,#LoadLevelShowButton:checked:hover,#CleanupSettingsShowButton:checked:hover,#OutputSettingsShowButton:checked:hover,#FxSettingsPreviewShowButton:checked:hover{background-color:#303133}.button-tool,QToolButton,#CameraSettingsRadioButton::indicator,#ForceSquaredPixelButton,#SchematicBottomFrame QToolBar QToolButton,#EditToolLockButton::indicator,#flipCustomize{background-color:rgba(255,255,255,0);border:1 solid rgba(255,255,255,0);border-radius:2;color:#e4e5e9;margin:1;padding:0}.button-tool:hover,QToolButton:hover,#CameraSettingsRadioButton::indicator:hover,#ForceSquaredPixelButton:hover,#colorSliderAddButton:hover,#colorSliderSubButton:hover,#SchematicBottomFrame QToolBar QToolButton:hover,#EditToolLockButton::indicator:hover,#flipCustomize:hover{background-color:#6e7174;border-color:#6e7174;color:#e4e5e9}.button-tool:pressed,QToolButton:pressed,#CameraSettingsRadioButton::indicator:pressed,#ForceSquaredPixelButton:pressed,#colorSliderAddButton:pressed,#colorSliderSubButton:pressed,#SchematicBottomFrame QToolBar QToolButton:pressed,#EditToolLockButton::indicator:pressed,#flipCustomize:pressed{background-color:#2b2c2d;border-color:#262728;color:#e4e5e9}.button-tool:checked,QToolButton:checked,#CameraSettingsRadioButton::indicator:checked,#ForceSquaredPixelButton:checked,#SchematicBottomFrame QToolBar QToolButton:checked,#EditToolLockButton::indicator:checked,#flipCustomize:checked{background-color:#5385a6;border-color:#5385a6;color:#fff}.button-tool:checked:hover,QToolButton:checked:hover,#CameraSettingsRadioButton::indicator:checked:hover,#ForceSquaredPixelButton:checked:hover,#SchematicBottomFrame QToolBar QToolButton:checked:hover,#EditToolLockButton::indicator:checked:hover,#flipCustomize:checked:hover{background-color:#6c98b6;border-color:#6c98b6}.button-tool:disabled,QToolButton:disabled,#CameraSettingsRadioButton::indicator:disabled,#ForceSquaredPixelButton:disabled,#SchematicBottomFrame QToolBar QToolButton:disabled,#EditToolLockButton::indicator:disabled,#flipCustomize:disabled{color:#808080}.button-flat,PaletteViewer QToolBar QToolButton{background-color:none;border:0;border-radius:0;margin:0}.button-flat:hover,PaletteViewer QToolBar QToolButton:hover{background-color:#6e7174}.button-flat:pressed,PaletteViewer QToolBar QToolButton:pressed{background-color:#212223}.frame,.GroupBox,#LoadLevelFrame,#PsdSettingsGroupBox,#CleanupSettingsFrame,#OutputSettingsBox,#OutputSettingsCameraBox,#SolidLineFrame,#FunctionParametersPanel,QGroupBox{border:1 solid #212223;border-radius:2}.tab-container,#TabBarContainer{background-color:transparent;qproperty-BottomAboveLineColor:#323435;qproperty-BottomBelowLineColor:#212223}.tab-flat,#StyleEditorTabBar::tab,#PaletteTabBar::tab,#FxSettingsTabBar::tab{background-color:#323435;border-right:1 solid #212223;border-bottom:1 solid #212223;color:#94969a;padding:3 4 3 4}.tab-flat:hover,#StyleEditorTabBar::tab:hover,#PaletteTabBar::tab:hover,#FxSettingsTabBar::tab:hover{background-color:#414345;color:#94969a}.tab-flat:selected,#StyleEditorTabBar::tab:selected,#PaletteTabBar::tab:selected,#FxSettingsTabBar::tab:selected{background-color:#414345;color:#fff;border-bottom-color:#414345}.tab-flat:only-one,#StyleEditorTabBar::tab:only-one,#PaletteTabBar::tab:only-one,#FxSettingsTabBar::tab:only-one{margin:0}.tab-round{background-color:#323435;border-top:1 solid #212223;border-right:1 solid #212223;border-left:1 solid #212223;border-bottom:1 solid #212223;color:#94969a;margin:3 -1 0 0;padding:2 7 1 7}.tab-round:hover{background-color:#414345;color:#94969a}.tab-round:selected{background-color:#414345;border-top-right-radius:2;border-top-left-radius:2;border-bottom-color:#414345;color:#fff;margin:1 -1 -1 0;padding:2 7 2 7}.tab-round:only-one{margin:1 0 0 0;padding:3 7 3 7}.tab-round:last{margin-right:0;border-top-right-radius:2}.tab-round:first{border-top-left-radius:2}QWidget{background-color:#414345;color:#d6d8dd}QWidget:disabled{color:#808080}QFrame{border:0;margin:0;padding:0}QToolTip,#helpToolTip{background-color:#fff;border:1 solid #000;color:#000;padding:1 1}#DockSeparator,QMainWindow::separator,QSplitter::handle{background-color:#141516;height:4;width:4}#TDockPlaceholder{background-color:#F77272}TPanel{background-color:#141516}#TopBar{background:#414345;border:0;border-bottom:1 solid #212223;height:21}#TopBar #EditToolLockButton{background:#414345;spacing:0}#TopBar #EditToolLockButton::indicator{background:none;border:none;height:18;margin:1 2 0 0;padding-left:0;padding-right:0}#TopBarTabContainer{background-color:#414345;margin-bottom:1}#StackedMenuBar{border:0;margin:0;padding:0}QMenuBar{background-color:#414345;border:0}QMenuBar::item{background-color:#414345;border-left:1 solid #414345;margin:0;padding:3 5}QMenuBar::item:selected{background-color:rgba(255,255,255,0.15);color:#d6d8dd}QMenuBar::item:pressed{background-color:#5385a6;color:#fff}#TopBarTab{margin:0;padding:0}#TopBarTab::tab{background-color:#323435;border-top:1 solid #212223;border-right:1 solid #212223;color:#94969a;margin:0 0 0 0;padding:2 8 3 8}#TopBarTab::tab:hover{background-color:#414345;color:#94969a}#TopBarTab::tab:selected{background-color:#414345;color:#fff}#TopBarTab::tab:first{border-left:1 solid #212223}#TopBarTab::tab:last{border-right:1 solid #212223}QMenu{background-color:#414345;border:1 solid #212223;padding:2 0}QMenu::item{padding:3 28}QMenu::item:selected{background-color:#5385a6;color:#fff}QMenu::item:checked{color:#d6d8dd}QMenu::item:checked:selected{background-color:#5385a6;color:#fff}QMenu::item:disabled{background:none;color:#808080}QMenu::item:disabled:selected{border-color:transparent}QMenu::separator{border-top:1 solid #212223;height:0;margin:2 0}QMenu::icon{border-radius:2;margin:0 0 0 3;padding:1}QMenu::icon:checked{background-color:#5385a6}QMenu::indicator{margin-left:7}TPanelTitleBar{background-color:#323435;border-color:#212223;border-style:solid;border-width:0 0 1 0;height:20;min-height:20;qproperty-TitleColor:#8c9093;qproperty-ActiveTitleColor:#43AEE5;qproperty-BorderPixmap:url('none');qproperty-ActiveBorderPixmap:url('../Default/imgs/white/none');qproperty-FloatBorderPixmap:url('none');qproperty-FloatActiveBorderPixmap:url('../Default/imgs/white/none')}QAbstractScrollArea::corner{background-color:#2d2f30}QScrollBar{background-color:#2d2f30;border:0}QScrollBar:horizontal{height:16;margin:0}QScrollBar:vertical{margin:0;width:16}QScrollBar::handle{border:1 solid #4b4d50;border-radius:4}QScrollBar::handle:horizontal:hover,QScrollBar::handle:vertical:hover{background-color:#5f6265;border-color:#5f6265}QScrollBar::handle:horizontal:pressed,QScrollBar::handle:vertical:pressed{background-color:#72767a;border-color:#72767a}QScrollBar::handle:horizontal{background-color:#4b4d50;margin:3 16;min-width:20}QScrollBar::handle:vertical{background-color:#4b4d50;margin:16 3;min-height:20}QScrollBar::add-line{subcontrol-origin:margin;border:0}QScrollBar::add-line:horizontal{subcontrol-position:right;background-color:#2d2f30;margin:0;width:16}QScrollBar::add-line:vertical{subcontrol-position:bottom;background-color:#2d2f30;margin:0;height:16}QScrollBar::sub-line{border:0;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{subcontrol-position:left;background-color:#2d2f30;margin:0;width:16}QScrollBar::sub-line:vertical{subcontrol-position:top;background-color:#2d2f30;margin:0;height:16}QScrollBar::up-arrow:vertical{image:url('../Default/imgs/white/scroll-up.svg');image-position:center center}QScrollBar::up-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::down-arrow:vertical{image:url('../Default/imgs/white/scroll-down.svg');image-position:center center}QScrollBar::down-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::left-arrow:horizontal{image:url('../Default/imgs/white/scroll-left.svg');image-position:center center}QScrollBar::left-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::right-arrow:horizontal{image:url('../Default/imgs/white/scroll-right.svg');image-position:center center}QScrollBar::right-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::sub-page:horizontal,QScrollBar::add-page:horizontal,QScrollBar::sub-page:vertical,QScrollBar::add-page:vertical{background:none}QToolBar{padding:0}QToolBar::separator:horizontal{border-left:1 solid #212223;margin:0 1;width:0}QToolBar::separator:vertical{border-top:1 solid #212223;height:0;margin:1 0}QToolBar QLabel{margin-top:1}QToolBar QToolBar{border:0}QToolButton::menu-indicator{image:none}QToolButton::menu-button{border-image:none}.DvScrollWidget QPushButton,DvScrollWidget QPushButton,#ScrollLeftButton QPushButton,#ScrollRightButton QPushButton,#ScrollUpButton QPushButton,#ScrollDownButton QPushButton{background-color:#616467;border:0 solid red;border-radius:0;padding:0;max-width:16}.DvScrollWidget QPushButton:hover,DvScrollWidget QPushButton:hover,#ScrollLeftButton QPushButton:hover,#ScrollRightButton QPushButton:hover,#ScrollUpButton QPushButton:hover,#ScrollDownButton QPushButton:hover{background-color:#6e7174}.DvScrollWidget QPushButton:pressed,DvScrollWidget QPushButton:pressed,#ScrollLeftButton QPushButton:pressed,#ScrollRightButton QPushButton:pressed,#ScrollUpButton QPushButton:pressed,#ScrollDownButton QPushButton:pressed{background-color:#2b2c2d}#ScrollLeftButton,#ScrollRightButton,#ScrollUpButton,#ScrollDownButton{margin:0;min-width:16}#ScrollLeftButton{border-right:1 solid #212223;image:url('../Default/imgs/white/scroll-left.svg')}#ScrollRightButton{border-left:1 solid #212223;margin-left:3;image:url('../Default/imgs/white/scroll-right.svg')}#ScrollUpButton{image:url('../Default/imgs/white/scroll-up.svg')}#ScrollDownButton{image:url('../Default/imgs/white/scroll-down.svg')}#keyFrameNavigator{background:none;margin:0;padding:0}#keyFrameNavigator QToolButton{min-width:18}#keyFrameNavigator #PreviousKey{image:url('../Default/imgs/white/prevkey.svg')}#keyFrameNavigator #PreviousKey:hover{image:url('../Default/imgs/white/prevkey_over.svg')}#keyFrameNavigator #PreviousKey:disabled{image:url('../Default/imgs/white/prevkey_disabled.svg')}#keyFrameNavigator #NextKey{image:url('../Default/imgs/white/nextkey.svg')}#keyFrameNavigator #NextKey:hover{image:url('../Default/imgs/white/nextkey_over.svg')}#keyFrameNavigator #NextKey:disabled{image:url('../Default/imgs/white/nextkey_disabled.svg')}.treeview,QTreeWidget,QTreeView,#FunctionEditorTree{background-color:#2d2f30;alternate-background-color:#323435;border:0;margin:0;outline:0}.treeview::item:selected,QTreeWidget::item:selected,QTreeView::item:selected,#FunctionEditorTree::item:selected{background-color:#5385a6;color:#fff}.treeview::branch:adjoins-item,QTreeWidget::branch:adjoins-item,QTreeView::branch:adjoins-item,#FunctionEditorTree::branch:adjoins-item{border-image:url('')}.treeview::branch:has-siblings,QTreeWidget::branch:has-siblings,QTreeView::branch:has-siblings,#FunctionEditorTree::branch:has-siblings{border-image:url('')}.treeview::branch:has-siblings:adjoins-item,QTreeWidget::branch:has-siblings:adjoins-item,QTreeView::branch:has-siblings:adjoins-item,#FunctionEditorTree::branch:has-siblings:adjoins-item{border-image:url('')}.treeview::branch:has-children:closed,QTreeWidget::branch:has-children:closed,QTreeView::branch:has-children:closed,#FunctionEditorTree::branch:has-children:closed{background:url('../Default/imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:open,QTreeWidget::branch:has-children:open,QTreeView::branch:has-children:open,#FunctionEditorTree::branch:has-children:open{background:url('../Default/imgs/white/treebranch-open.svg') no-repeat;background-position:center center;image:none}.treeview::branch:has-children:has-siblings:closed,QTreeWidget::branch:has-children:has-siblings:closed,QTreeView::branch:has-children:has-siblings:closed,#FunctionEditorTree::branch:has-children:has-siblings:closed{background:url('../Default/imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:has-siblings:open,QTreeWidget::branch:has-children:has-siblings:open,QTreeView::branch:has-children:has-siblings:open,#FunctionEditorTree::branch:has-children:has-siblings:open{background:url('../Default/imgs/white/treebranch-open.svg') no-repeat;background-position:center center;border-image:none;image:none}QListView{outline:0;background:#2d2f30;alternate-background-color:#323435}#TabBarContainer{background-color:#323435}.Button,QPushButton,.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{background-color:#616467;border:1 solid #414345;border-radius:2;color:#e4e5e9;margin:0;padding:3 15}.Button:hover,QPushButton:hover,.ComboBox:hover,#ViewerFpsSlider::sub-line:horizontal:hover,#ViewerFpsSlider::add-line:horizontal:hover,QComboBox:hover{background-color:#6e7174;border-color:#414345;color:#e4e5e9}.Button:pressed,QPushButton:pressed,#ViewerFpsSlider::sub-line:horizontal:pressed,#ViewerFpsSlider::add-line:horizontal:pressed{background-color:#2b2c2d;border-color:#262728;color:#e4e5e9}.Button:checked,QPushButton:checked{background-color:#2b2c2d;border-color:#262728;color:#e4e5e9}.Button:checked:hover,QPushButton:checked:hover{background-color:#303133}.Button:checked:hover:pressed,QPushButton:checked:hover:pressed{background:#2b2c2d}.Button:disabled,QPushButton:disabled,.ComboBox:disabled,#ViewerFpsSlider::sub-line:horizontal:disabled,#ViewerFpsSlider::add-line:horizontal:disabled,QComboBox:disabled{background-color:#4d5052;border-color:#414345;color:#808080}#PushButton_NoPadding{padding:3}.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{padding:1 0 1 4;margin:1 0}.ComboBox::drop-down,QComboBox::drop-down{image:url('../Default/imgs/white/combo_downarrow.svg');image-position:center center;width:16}.ComboBox::drop-down:disabled,QComboBox::drop-down:disabled{image:url('../Default/imgs/white/combo_downarrow_disabled.svg')}.ComboBox QAbstractItemView,QComboBox QAbstractItemView{background-color:#414345;border:1 solid #212223;selection-background-color:#5385a6;selection-color:#fff}.LineEdit,QLineEdit,#TaskSheetItem,#tasksRemoveBox,#tasksAddBox{background-color:#28292b;border:1 solid #262728;border-radius:2;color:#d6d8dd;selection-background-color:#5385a6;selection-color:#fff;padding:0 0 0 1}.LineEdit:focus,QLineEdit:focus,#TaskSheetItem:focus,#tasksRemoveBox:focus,#tasksAddBox:focus{background-color:#28292b;border-color:#5385a6;color:#d6d8dd}.LineEdit:disabled,QLineEdit:disabled,#TaskSheetItem:disabled,#tasksRemoveBox:disabled,#tasksAddBox:disabled{background-color:#353638;border-color:#333537;color:#808080}.CheckBox,QCheckBox{color:#d6d8dd}.CheckBox:hover,QCheckBox:hover,.RadioButton:hover,QRadioButton:hover{color:#fff}.CheckBox:disabled,QCheckBox:disabled{color:#808080}.CheckBox::indicator,QMenu::indicator,QCheckBox::indicator,.GroupBox::indicator,QGroupBox::indicator{background-color:#28292b;border:1 solid #262728;border-radius:2;height:9;padding:1;width:9}.CheckBox::indicator:hover,QMenu::indicator:hover,.CheckBox::indicator:checked:hover,QCheckBox::indicator:hover,.GroupBox::indicator:hover,QMenu::indicator:checked:hover,QCheckBox::indicator:checked:hover,.GroupBox::indicator:checked:hover,QGroupBox::indicator:hover,QGroupBox::indicator:checked:hover{background-color:#28292b;border-color:#5385a6}.CheckBox::indicator:checked,QMenu::indicator:checked,QCheckBox::indicator:checked,.GroupBox::indicator:checked,QGroupBox::indicator:checked{background-color:#28292b;border-color:#262728;image:url('../Default/imgs/white/checkmark.svg')}.CheckBox::indicator:checked:disabled,QMenu::indicator:checked:disabled,QCheckBox::indicator:checked:disabled,.GroupBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled{background-color:#353638;border-color:#353638;image:url('../Default/imgs/white/checkmark_disabled.svg')}.CheckBox::indicator:disabled,QMenu::indicator:disabled,QCheckBox::indicator:disabled,.GroupBox::indicator:disabled,QGroupBox::indicator:disabled{background-color:#353638;border-color:#353638}.RadioButton::indicator:unchecked,QRadioButton::indicator:unchecked,#CameraSettingsRadioButton_Small::indicator:unchecked{image:url('../Default/imgs/white/radiobutton_unchecked.svg');image-position:center center}.RadioButton::indicator:checked,QRadioButton::indicator:checked,#CameraSettingsRadioButton_Small::indicator:checked{image:url('../Default/imgs/white/radiobutton_checked.svg');image-position:center center}.GroupBox,QGroupBox{margin:6 0 0 0;padding:5 0}.GroupBox::title,QGroupBox::title{subcontrol-origin:margin;left:15;margin:-3 0 0 0;padding:0 3}.GroupBox::title:hover,QGroupBox::title:hover{color:#fff}.GroupBox::title:disabled,QGroupBox::title:disabled{color:#808080}.GroupBox::indicator,QGroupBox::indicator{subcontrol-origin:margin;margin-top:2}.GroupBox:disabled,QGroupBox:disabled{color:#808080}.Slider::groove:horizontal,QSlider::groove:horizontal{background-color:transparent;background-image:url('../Default/imgs/white/slider-groove.svg');background-position:center center;background-repeat:repeat-x;margin:0;height:20;min-height:20}.Slider::groove:horizontal:disabled,QSlider::groove:horizontal:disabled{background-image:url('../Default/imgs/white/slider-groove_disabled.svg')}.Slider::handle:horizontal,QSlider::handle:horizontal{width:10;margin:-2 -1;image:url('../Default/imgs/white/slider-handle.svg')}.Slider::handle:horizontal:disabled,QSlider::handle:horizontal:disabled{image:url('../Default/imgs/white/slider-handle_disabled.svg')}#IntPairField,#DoublePairField{qproperty-LightLineColor:#262728;qproperty-LightLineEdgeColor:#262728;qproperty-DarkLineColor:#262728;qproperty-MiddleLineColor:#262728;qproperty-HandleLeftPixmap:url("../Default/imgs/white/slider-handle.svg");qproperty-HandleRightPixmap:url("../Default/imgs/white/slider-handle.svg");qproperty-HandleLeftGrayPixmap:url("../Default/imgs/white/slider-handle_disabled.svg");qproperty-HandleRightGrayPixmap:url("../Default/imgs/white/slider-handle_disabled.svg")}#DirTreeView{background-color:#2d2f30;alternate-background-color:#2d2f30;border:1 solid #212223;border-right:0}DvItemViewerPanel{qproperty-TextColor:#d6d8dd;qproperty-AlternateBackground:#3a3b3d;qproperty-SelectedTextColor:#fff;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedItemBackground:#5385a6}#FileBrowser DvItemViewerPanel,#SceneCast DvItemViewerPanel{background-color:#414345}#FileBrowser #castFrame,#SceneCast #castFrame{border-top:1 solid #212223;border-right:1 solid #212223;border-bottom:1 solid #212223;margin:0}#FileBrowser QToolButton,#SceneCast QToolButton{padding:1}DvDirTreeView{qproperty-TextColor:#d6d8dd;qproperty-SelectedTextColor:#fff;qproperty-SelectedItemBackground:#5385a6;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedFolderTextColor:#fff;alternate-background-color:#323435;background-color:#2d2f30;border:1 solid #212223}#FileDoesNotExistLabel{color:#f00}#SceneCast QToolBar{border-top:1 solid #212223}#SceneCast QToolButton{margin:3 1 2 1;padding:1}#CastBrowser{border:0;margin:0}#FilmStrip QComboBox{border-radius:0;border-width:0}#FilmStrip QComboBox QAbstractItemView{background-color:#414345}#CleanupSettings #CleanupSettingsFrame{margin-top:2;margin-bottom:4}#CleanupSettings QGroupBox{margin-bottom:3}ParamsPage{qproperty-TextColor:#d6d8dd}#CameraSettingsButton{padding:2}#CameraSettingsRadioButton:hover{background:none}#CameraSettingsRadioButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#CameraSettingsRadioButton::indicator:unchecked{image:url('../Default/imgs/white/lock_off.svg')}#CameraSettingsRadioButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('../Default/imgs/white/lock_on.svg')}#CameraSettingsRadioButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#CameraSettingsDPI{color:#9fdaff}#CameraSettingsRadioButton_Small{padding:0}#CameraSettingsRadioButton_Small::indicator{background-color:transparent;border:0;height:21;margin:0;width:11}#ForceSquaredPixelButton{height:16;border:1 solid rgba(255,255,255,0);image:url('../Default/imgs/white/fsp_unchecked.svg');padding:2;width:16;margin:0}#ForceSquaredPixelButton:checked{image:url('../Default/imgs/white/fsp_checked.svg')}#OutputSettingsLabel{color:#9fdaff}PencilTestPopup{min-height:730px;min-width:512px}#MatchLineButton{background-color:#66696c}#MatchLineButton:checked{background-color:#8c9093;border:2 solid #5385a6;border-radius:2}#LargeSizedText{font-size:17}#StartupLabel{padding:3}#StartupLabel:hover{background:#5a5d5f}QStatusBar{background-color:#c0c0c0}QStatusBar::item{border:0}QStatusBar QLabel{background-color:#c0c0c0}QStatusBar #StatusBarLabel{background-color:#fff;padding:1 3}#TitleTxtLabel{color:#9fdaff}#StyleEditor QPushButton{margin:2 1;padding:0}#StyleEditor #TabBarContainer{margin-left:-4}#StyleEditor #bottomWidget{border-top:1 solid #212223;padding:3 2 8 3}#StyleEditor #bottomWidget QPushButton{padding:3 5}#StyleEditorTabBar::tab::first{border-left:1 solid #212223}#HexagonalColorWheel{qproperty-BGColor:#414345}#colorSlider::groove:horizontal{height:1;border-image:none}#colorSlider::handle:horizontal{width:8;margin:-8 -4}#colorSliderAddButton,#colorSliderSubButton{background:none;border-color:transparent;image-position:center center;min-height:16;padding:0;min-width:18}#colorSliderAddButton{image:url('../Default/imgs/white/scroll-right.svg')}#colorSliderSubButton{image:url('../Default/imgs/white/scroll-left.svg')}#PlainColorPageParts{border-bottom:1 solid #212223}#PlainColorPageParts QLineEdit{max-width:35}PaletteViewer DvScrollWidget QPushButton{border-top:0;margin-bottom:1;max-width:15;min-width:15}PaletteViewer DvScrollWidget #ScrollLeftButton{border-radius:0;margin-bottom:1;max-width:16;min-width:16}PaletteViewer DvScrollWidget #ScrollRightButton{border-radius:0;margin-left:1;margin-bottom:1;max-width:16;min-width:16}PaletteViewer QToolBar{background:none;border-bottom:1 solid #212223;padding:0;margin:0}PaletteViewer QToolBar::separator:horizontal{margin:0}PaletteViewer QToolBar QToolButton{margin:0 0 1 0;padding:1 0 2 0}#PageViewer{qproperty-TextColor:#d6d8dd}#PaletteLockButton{border-radius:0;margin:0 0 1 1}#PaletteLockButton:checked{background-color:#C34040;border-color:#C34040}#PaletteLockButton:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#WordButton{padding-right:0;padding-left:0}QDialog{background-color:#414345}QDialog #dialogButtonFrame{background-color:#37393a;border-top:1 solid #212223}QDialog #dialogButtonFrame QPushButton{border-color:#37393a;outline:0}QDialog #dialogButtonFrame QPushButton:focus{background-color:#5385a6;border-color:#37393a;color:#fff}QDialog #dialogButtonFrame QPushButton:focus:hover{background-color:#6c98b6}QDialog #dialogButtonFrame QPushButton:focus:pressed{background-color:#2b2c2d;border-color:#262728;color:#e4e5e9}#SceneSettings QLabel{color:#9fdaff}#PreferencesPopup QListWidget{background-color:#2d2f30;alternate-background-color:#2d2f30;border:1 solid #212223;font-size:13}#PreferencesPopup QListWidget::item{border:0;padding:3}#PreferencesPopup QListWidget::item:hover{color:#d6d8dd;background-color:rgba(255,255,255,0.15)}#PreferencesPopup QListWidget::item:selected{background-color:#5385a6;color:#fff}#ShortcutTree{border:1 solid #212223}#ShortcutTree::item{padding:1 0}#ShortcutTree QScrollBar:vertical{width:16;margin-right:-1}ProjectPopup QLabel{color:#9fdaff}#GearButton{qproperty-icon:url('../Default/imgs/white/gear.svg')}#SubfolderButton{qproperty-icon:url('../Default/imgs/white/subfolder.svg')}SchematicViewer{qproperty-TextColor:#d6d8dd;qproperty-VerticalLineColor:#222;qproperty-LevelColumnColor:#4C6E4C;qproperty-VectorColumnColor:#7B7B4C;qproperty-ChildColumnColor:#6A526B;qproperty-FullcolorColumnColor:#657A96;qproperty-FxColumnColor:#56553C;qproperty-PaletteColumnColor:#3A655F;qproperty-MeshColumnColor:#684D86;qproperty-ReferenceColumnColor:#616161;qproperty-TableColor:#62628c;qproperty-ActiveCameraColor:#2d7dca;qproperty-OtherCameraColor:#6c797b;qproperty-GroupColor:#3b6e9c;qproperty-PegColor:#9f6e3c;qproperty-SplineColor:#6a9d1c;qproperty-ActiveOutputColor:#2d7dca;qproperty-OtherOutputColor:#6c797b;qproperty-XsheetColor:#62628c;qproperty-NormalFxColor:#6a7e96;qproperty-MacroFxColor:#815c79;qproperty-ImageAdjustFxColor:#656287;qproperty-LayerBlendingFxColor:#4f757d;qproperty-MatteFxColor:#ae7171;qproperty-SchematicPreviewButtonBgOnColor:#c8c864;qproperty-SchematicPreviewButtonOnImage:url('../Default/imgs/white/x_prev_eye_on.svg');qproperty-SchematicPreviewButtonBgOffColor:#616161;qproperty-SchematicPreviewButtonOffImage:url('../Default/imgs/white/x_prev_eye_off.svg');qproperty-SchematicCamstandButtonBgOnColor:#eb906b;qproperty-SchematicCamstandButtonOnImage:url('../Default/imgs/white/x_table_view_on.svg');qproperty-SchematicCamstandButtonTranspImage:url('../Default/imgs/white/x_table_view_transp.svg');qproperty-SchematicCamstandButtonBgOffColor:#616161;qproperty-SchematicCamstandButtonOffImage:url('../Default/imgs/white/x_table_view_off.svg')}#SchematicBottomFrame{background-color:#414345;border:0;margin:0;padding:0}#SchematicBottomFrame QToolBar::separator:horizontal{margin:0}#SchematicBottomFrame QToolBar QToolButton{padding:0;margin:2}#SchematicSceneViewer{background-color:#353638;border-bottom:1 solid #212223}#FxSettingsTabBar::tab{border-top:1 solid #212223}#FxSettingsTabBar::tab::first,#FxSettingsTabBar::tab::only-one{border-left:1 solid #212223}FxSettings QToolBar{border-top:1 solid #212223;border-right:1 solid #212223;border-left:1 solid #212223;min-height:23;padding:3 0}FxSettings QToolBar QToolBar{border:0}#FxSettingsLabel{color:#a0e680}#FxSettingsHelpButton{background-color:#80a0dc;color:#000;padding-top:0;padding-bottom:0}#FxSettingsHelpButton:hover{background-color:#a8bee7}#ScriptConsole{font-family:'Courier New',monospace;border:0;color:#000000;padding:3}#ScriptConsole QFrame{background-color:#dcdcdc}#ScriptConsole TPanelTitleBar{background-color:#323435}#TaskSheetItemLabel{color:#d6d8dd}#Tasks QToolBar{border-bottom:1 solid #212223;margin:0;padding:0}#Tasks QToolBar QToolButton{margin:2 2 3 2}#ToolBar QToolBar{padding-left:2}#ToolOptions TPanelTitleBar{border-right:1 solid #212223;border-bottom:0}#CommandBar TPanelTitleBar{border-right:1 solid #212223;border-bottom:0}IconViewField{qproperty-ThicknessPixmap:url("../Default/imgs/white/selectiontool_thickness.svg")}#EditToolLockButton{spacing:0}#EditToolLockButton:hover{background:none}#EditToolLockButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#EditToolLockButton::indicator:unchecked{image:url('../Default/imgs/white/lock_off.svg')}#EditToolLockButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('../Default/imgs/white/lock_on.svg')}#EditToolLockButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}PopupButton::menu-indicator{border-left:0;height:17;image:url('../Default/imgs/white/combo_downarrow.svg');width:10}PopupButton::menu-indicator:hover{image:url('../Default/imgs/white/combo_downarrow.svg')}PopupButton::menu-indicator:disabled{image:url('../Default/imgs/white/combo_downarrow_disabled.svg')}#Cap,#Join{padding:0 4 0 -8;max-width:32;min-width:32}#Cap QMenu,#Join QMenu{max-width:28;min-width:28}#Cap QMenu::item,#Join QMenu::item{max-width:28;min-width:28;padding:0}QToolBar#MediumPaddingToolBar QToolButton{padding-left:3;padding-right:3}QToolBar#WidePaddingToolBar QToolButton{padding-left:6;padding-right:6}#CommandBar{margin:0;padding:0;border:0}#CommandBar::separator:horizontal{margin-right:3;margin-left:3}#expandButton:checked{background-color:transparent;border-color:transparent;color:#d6d8dd}#expandButton:checked:hover{background-color:#6e7174;border-color:#6e7174}#expandButton:checked:pressed{background-color:#2b2c2d;border-color:#262728}#ComboViewerPanel Toolbar{border-bottom:1 solid #212223}#ComboViewerPanel Toolbar::separator:horizontal{margin:0 0 0 2}#ComboViewerPanel Toolbar QToolButton{margin:2 0 3 2}#ComboViewerToolOptions{border-bottom:1 solid #212223}#ComboViewer #ToolBarContainer,#ViewerPanel #ToolBarContainer,FlipBook #ToolBarContainer{background-color:transparent;border-top:2 solid #212223;border-bottom:1 solid #212223;padding-right:-1}#flipCustomize{margin-left:3}#flipCustomize::menu-button{background-color:transparent;width:35}#flipCustomize::menu-arrow{image:none}QToolBar#FlipConsolePlayToolBar::separator:horizontal{margin:0 3}QToolBar#FlipConsolePlayToolBar QToolButton{margin-top:2;margin-bottom:2;height:16;padding-left:1;padding-right:1}#ViewerFpsSlider{background-color:transparent;background-image:url('../Default/imgs/white/slider-groove.svg');background-position:center center;background-repeat:repeat-x;border:0;height:19;margin:0 3 0 37;max-width:300;min-width:0}#ViewerFpsSlider::sub-line:horizontal{subcontrol-origin:absolute;background-color:#616467;border:1 solid #414345;border-top-left-radius:2;border-bottom-left-radius:2;height:16;left:-33;width:14}#ViewerFpsSlider::add-line:horizontal{subcontrol-position:left;background-color:#616467;border:1 solid #414345;border-top-right-radius:2;border-bottom-right-radius:2;left:18;height:16;image-position:center center;width:13}#ViewerFpsSlider::handle::horizontal{background-color:#999c9f;border:1 solid #999c9f;border-radius:2;margin:2 0 3 0;min-width:9;width:9;max-width:9}FlipSlider{qproperty-PBHeight:15;qproperty-PBOverlay:url('../Default/imgs/white/flipslider.svg');qproperty-PBColorMarginLeft:1;qproperty-PBColorMarginTop:2;qproperty-PBColorMarginRight:1;qproperty-PBColorMarginBottom:2;qproperty-PBMarker:url('../Default/imgs/white/flipmarker.svg');qproperty-PBMarkerMarginLeft:3;qproperty-PBMarkerMarginRight:3;qproperty-notStartedColor:rgba(205,101,101,0.78);qproperty-startedColor:#1abc3f;qproperty-baseColor:#28292b;qproperty-finishedColor:#28292b}Ruler{qproperty-ParentBGColor:#414345;qproperty-ScaleColor:#d6d8dd}#RulerToolOptionValues{color:#000}#xsheetArea,#ScrollArea{background-color:#2d2f30;border:0}#xsheetScrollArea{border:0}#cornerWidget QToolButton{padding:0}#xsheetColumnAreaMenu_Preview{background-color:#E6E678}#xsheetColumnAreaMenu_Lock{background-color:#F5F5F5}#xsheetColumnAreaMenu_Camstand{background-color:#FFA480}#xsheetColumnAreaMenu_Preview,#xsheetColumnAreaMenu_Lock,#xsheetColumnAreaMenu_Camstand{color:#000}#noteTextEdit{color:#000}XsheetViewer{qproperty-TextColor:#d6d8dd;qproperty-BGColor:#353638;qproperty-LightLineColor:#262728;qproperty-MarkerLineColor:#1E96C4;qproperty-VerticalLineColor:#222;qproperty-VerticalLineHeadColor:#777b7f;qproperty-PreviewFrameTextColor:#9fdaff;qproperty-CurrentRowBgColor:#506082;qproperty-OnionSkinAreaBgColor:#303133;qproperty-EmptyColumnHeadColor:#5a5d60;qproperty-SelectedColumnTextColor:#E66464;qproperty-EmptyCellColor:#393b3d;qproperty-NotEmptyColumnColor:#414345;qproperty-SelectedEmptyCellColor:#64676a;qproperty-LevelColumnColor:#4C6E4C;qproperty-LevelColumnBorderColor:#8FB38F;qproperty-SelectedLevelColumnColor:#678667;qproperty-VectorColumnColor:#7B7B4C;qproperty-VectorColumnBorderColor:#BBBB9A;qproperty-SelectedVectorColumnColor:#949466;qproperty-ChildColumnColor:#6A526B;qproperty-ChildColumnBorderColor:#B1A3B3;qproperty-SelectedChildColumnColor:#816e82;qproperty-FullcolorColumnColor:#657A96;qproperty-FullcolorColumnBorderColor:#9EB8BB;qproperty-SelectedFullcolorColumnColor:#8895a6;qproperty-FxColumnColor:#56553C;qproperty-FxColumnBorderColor:#95958A;qproperty-SelectedFxColumnColor:#6f6e56;qproperty-ReferenceColumnColor:#616161;qproperty-ReferenceColumnBorderColor:#A2A2A2;qproperty-SelectedReferenceColumnColor:#7a7a7a;qproperty-PaletteColumnColor:#3A655F;qproperty-PaletteColumnBorderColor:#86ACA7;qproperty-SelectedPaletteColumnColor:#52807a;qproperty-MeshColumnColor:#684D86;qproperty-MeshColumnBorderColor:#BA92EF;qproperty-SelectedMeshColumnColor:#82689e;qproperty-SoundTextColumnColor:#c8c8c8;qproperty-SoundTextColumnBorderColor:#8c8c8c;qproperty-SelectedSoundTextColumnColor:#e2e2e2;qproperty-SoundColumnColor:#657456;qproperty-SoundColumnBorderColor:#A0AF7D;qproperty-SelectedSoundColumnColor:#7e8b72;qproperty-SoundColumnHlColor:#34FE5E;qproperty-SoundColumnTrackColor:#B6C29D;qproperty-ColumnHeadPastelizer:#000;qproperty-SelectedColumnHead:#506082;qproperty-LightLightBGColor:#393b3d;qproperty-LightBGColor:#eaebec;qproperty-DarkBGColor:#dbdcdd;qproperty-DarkLineColor:#8e9194;qproperty-XsheetColumnNameBgColor:rgba(0,0,0,0);qproperty-XsheetDragBarHighlightColor:rgba(255,255,255,0.5);qproperty-XsheetPreviewButtonBgOnColor:#c8c864;qproperty-XsheetPreviewButtonOnImage:url('../Default/imgs/white/x_prev_eye_on.svg');qproperty-XsheetPreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetPreviewButtonOffImage:url('../Default/imgs/white/x_prev_eye_off.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');qproperty-XsheetCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetCamstandButtonOffImage:url('../Default/imgs/white/x_table_view_off.svg');qproperty-XsheetLockButtonBgOnColor:rgba(255,255,255,0.3);qproperty-XsheetLockButtonOnImage:url('../Default/imgs/white/x_lock_on.svg');qproperty-XsheetLockButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetLockButtonOffImage:url('../Default/imgs/white/x_lock_off.svg');qproperty-XsheetConfigButtonBgColor:rgba(255,255,255,0);qproperty-XsheetConfigButtonImage:url('../Default/imgs/white/x_config.svg');qproperty-TimelinePreviewButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelinePreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineCamstandButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelineCamstandButtonTranspImage:url('../Default/imgs/white/timeline_toggle_transp.svg');qproperty-TimelineCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineLockButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelineLockButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineConfigButtonBgColor:rgba(255,255,255,0);qproperty-TimelineConfigButtonImage:url('../Default/imgs/white/timeline_config.svg');qproperty-LayerHeaderPreviewImage:url('../Default/imgs/white/layer_header_prev_eye.svg');qproperty-LayerHeaderPreviewOverImage:url('../Default/imgs/white/layer_header_prev_eye_over.svg');qproperty-LayerHeaderCamstandImage:url('../Default/imgs/white/layer_header_table_view.svg');qproperty-LayerHeaderCamstandOverImage:url('../Default/imgs/white/layer_header_table_view_over.svg');qproperty-LayerHeaderLockImage:url('../Default/imgs/white/lock_on.svg');qproperty-LayerHeaderLockOverImage:url('../Default/imgs/white/lock_on_over.svg')}#XSheetToolbar{margin:0;padding:0;border:0}#XSheetToolbar QToolButton{padding:0;margin:4 1;min-height:19;height:19}#XSheetToolbar::separator:horizontal{margin:0 4}#FunctionEditor QToolBar{border-bottom:1 solid #212223}#FunctionEditor QToolBar QToolBar{border:0}#FunctionEditor QToolBar QLabel{margin-left:5}#FunctionEditor QToolBar QToolButton{height:18}#FunctionEditorTree{border-top:1 solid #212223}FunctionTreeView{qproperty-TextColor:#d6d8dd;qproperty-CurrentTextColor:#E66464}FunctionPanel{qproperty-BGColor:#343638;qproperty-ValueLineColor:#28292b;qproperty-FrameLineColor:#28292b;qproperty-OtherCurvesColor:#7f8386;qproperty-RulerBackground:#2d2e30;qproperty-TextColor:#d6d8dd;qproperty-SubColor:#000;qproperty-SelectedColor:#FFA500}SpreadsheetViewer{qproperty-LightLightBGColor:#393b3d;qproperty-CurrentRowBgColor:#506082;qproperty-LightLineColor:#262728;qproperty-MarkerLineColor:#1E96C4;qproperty-BGColor:#414345;qproperty-VerticalLineColor:#222;qproperty-KeyFrameColor:#995d1d;qproperty-KeyFrameBorderColor:#c9b04b;qproperty-SelectedKeyFrameColor:#be772b;qproperty-InBetweenColor:#666250;qproperty-InBetweenBorderColor:#cdcec8;qproperty-SelectedInBetweenColor:#7d7a6c;qproperty-SelectedEmptyColor:#64676a;qproperty-SelectedSceneRangeEmptyColor:#6d7073;qproperty-TextColor:#d6d8dd;qproperty-ColumnHeaderBorderColor:#777b7f;qproperty-SelectedColumnTextColor:#E66464}#ExpressionField{background-color:#e0e1e2;border:1 solid #2d2e2f;margin:0}#FunctionSegmentViewerLinkButton{background-image:url('../Default/imgs/white/segment_unlinked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:hover{background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:checked{background-image:url('../Default/imgs/white/segment_linked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:disabled{background-image:url('../Default/imgs/white/segment_disabled.svg');background-repeat:no-repeat} \ No newline at end of file diff --git a/stuff/config/qss/Dark/Dark.qss b/stuff/config/qss/Dark/Dark.qss index d51ba74..646d28d 100644 --- a/stuff/config/qss/Dark/Dark.qss +++ b/stuff/config/qss/Dark/Dark.qss @@ -1 +1 @@ -.button-show,#LoadLevelShowButton,#CleanupSettingsShowButton,#OutputSettingsShowButton,#FxSettingsPreviewShowButton{image:url('../Default/imgs/white/plus.svg');image-position:center center;margin:0;padding:1;min-width:10;min-height:10}.button-show:checked,#LoadLevelShowButton:checked,#CleanupSettingsShowButton:checked,#OutputSettingsShowButton:checked,#FxSettingsPreviewShowButton:checked{background-color:#191919;border-color:#141414;image:url('../Default/imgs/white/minus.svg')}.button-show:checked:pressed,#LoadLevelShowButton:checked:pressed,#CleanupSettingsShowButton:checked:pressed,#OutputSettingsShowButton:checked:pressed,#FxSettingsPreviewShowButton:checked:pressed{background-color:#191919;border-color:#141414}.button-show:checked:hover,#LoadLevelShowButton:checked:hover,#CleanupSettingsShowButton:checked:hover,#OutputSettingsShowButton:checked:hover,#FxSettingsPreviewShowButton:checked:hover{background-color:#1e1e1e}.button-tool,QToolButton,#CameraSettingsRadioButton::indicator,#ForceSquaredPixelButton,#SchematicBottomFrame QToolBar QToolButton,#EditToolLockButton::indicator,#flipCustomize{background-color:rgba(255,255,255,0);border:1 solid rgba(255,255,255,0);border-radius:2;color:#dbdbdb;margin:1;padding:0}.button-tool:hover,QToolButton:hover,#CameraSettingsRadioButton::indicator:hover,#ForceSquaredPixelButton:hover,#colorSliderAddButton:hover,#colorSliderSubButton:hover,#SchematicBottomFrame QToolBar QToolButton:hover,#EditToolLockButton::indicator:hover,#flipCustomize:hover{background-color:#5e5e5e;border-color:#5e5e5e;color:#dbdbdb}.button-tool:pressed,QToolButton:pressed,#CameraSettingsRadioButton::indicator:pressed,#ForceSquaredPixelButton:pressed,#colorSliderAddButton:pressed,#colorSliderSubButton:pressed,#SchematicBottomFrame QToolBar QToolButton:pressed,#EditToolLockButton::indicator:pressed,#flipCustomize:pressed{background-color:#191919;border-color:#141414;color:#dbdbdb}.button-tool:checked,QToolButton:checked,#CameraSettingsRadioButton::indicator:checked,#ForceSquaredPixelButton:checked,#SchematicBottomFrame QToolBar QToolButton:checked,#EditToolLockButton::indicator:checked,#flipCustomize:checked{background-color:#5385a6;border-color:#5385a6;color:#fff}.button-tool:checked:hover,QToolButton:checked:hover,#CameraSettingsRadioButton::indicator:checked:hover,#ForceSquaredPixelButton:checked:hover,#SchematicBottomFrame QToolBar QToolButton:checked:hover,#EditToolLockButton::indicator:checked:hover,#flipCustomize:checked:hover{background-color:#6c98b6;border-color:#6c98b6}.button-tool:disabled,QToolButton:disabled,#CameraSettingsRadioButton::indicator:disabled,#ForceSquaredPixelButton:disabled,#SchematicBottomFrame QToolBar QToolButton:disabled,#EditToolLockButton::indicator:disabled,#flipCustomize:disabled{color:#808080}.button-flat,PaletteViewer QToolBar QToolButton{background-color:none;border:0;border-radius:0;margin:0}.button-flat:hover,PaletteViewer QToolBar QToolButton:hover{background-color:#5e5e5e}.button-flat:pressed,PaletteViewer QToolBar QToolButton:pressed{background-color:#161616}.frame,.GroupBox,#LoadLevelFrame,#PsdSettingsGroupBox,#CleanupSettingsFrame,#OutputSettingsBox,#OutputSettingsCameraBox,#SolidLineFrame,#FunctionParametersPanel,QGroupBox{border:1 solid #161616;border-radius:2}.tab-container,#TabBarContainer{background-color:transparent;qproperty-BottomAboveLineColor:#262626;qproperty-BottomBelowLineColor:#161616}.tab-flat,#StyleEditorTabBar::tab,#PaletteTabBar::tab,#FxSettingsTabBar::tab{background-color:#262626;border-right:1 solid #161616;border-bottom:1 solid #161616;color:#8b8b8b;padding:3 4 3 4}.tab-flat:hover,#StyleEditorTabBar::tab:hover,#PaletteTabBar::tab:hover,#FxSettingsTabBar::tab:hover{background-color:#303030;color:#8b8b8b}.tab-flat:selected,#StyleEditorTabBar::tab:selected,#PaletteTabBar::tab:selected,#FxSettingsTabBar::tab:selected{background-color:#303030;color:#f4f4f4;border-bottom-color:#303030}.tab-flat:only-one,#StyleEditorTabBar::tab:only-one,#PaletteTabBar::tab:only-one,#FxSettingsTabBar::tab:only-one{margin:0}.tab-round{background-color:#262626;border-top:1 solid #161616;border-right:1 solid #161616;border-left:1 solid #161616;border-bottom:1 solid #161616;color:#8b8b8b;margin:3 -1 0 0;padding:2 7 1 7}.tab-round:hover{background-color:#303030;color:#8b8b8b}.tab-round:selected{background-color:#303030;border-top-right-radius:2;border-top-left-radius:2;border-bottom-color:#303030;color:#f4f4f4;margin:1 -1 -1 0;padding:2 7 2 7}.tab-round:only-one{margin:1 0 0 0;padding:3 7 3 7}.tab-round:last{margin-right:0;border-top-right-radius:2}.tab-round:first{border-top-left-radius:2}QWidget{background-color:#303030;color:#cecece}QWidget:disabled{color:#808080}QFrame{border:0;margin:0;padding:0}QToolTip,#helpToolTip{background-color:#fff;border:1 solid #000;color:#000;padding:1 1}#DockSeparator,QMainWindow::separator,QSplitter::handle{background-color:#0c0c0c;height:4;width:4}#TDockPlaceholder{background-color:#F77272}TPanel{background-color:#0c0c0c}#TopBar{background:#303030;border:0;border-bottom:1 solid #161616;height:21}#TopBar #EditToolLockButton{background:#303030;spacing:0}#TopBar #EditToolLockButton::indicator{background:none;border:none;height:18;margin:1 2 0 0;padding-left:0;padding-right:0}#TopBarTabContainer{background-color:#303030;margin-bottom:1}#StackedMenuBar{border:0;margin:0;padding:0}QMenuBar{background-color:#303030;border:0}QMenuBar::item{background-color:#303030;border-left:1 solid #303030;margin:0;padding:3 5}QMenuBar::item:selected{background-color:rgba(255,255,255,0.15);color:#cecece}QMenuBar::item:pressed{background-color:#5385a6;color:#fff}#TopBarTab{margin:0;padding:0}#TopBarTab::tab{background-color:#262626;border-top:1 solid #161616;border-right:1 solid #161616;color:#8b8b8b;margin:0 0 0 0;padding:2 8 3 8}#TopBarTab::tab:hover{background-color:#303030;color:#8b8b8b}#TopBarTab::tab:selected{background-color:#303030;color:#f4f4f4}#TopBarTab::tab:first{border-left:1 solid #161616}#TopBarTab::tab:last{border-right:1 solid #161616}QMenu{background-color:#303030;border:1 solid #161616;padding:2 0}QMenu::item{padding:3 28}QMenu::item:selected{background-color:#5385a6;color:#fff}QMenu::item:checked{color:#cecece}QMenu::item:checked:selected{background-color:#5385a6;color:#fff}QMenu::item:disabled{background:none;color:#808080}QMenu::item:disabled:selected{border-color:transparent}QMenu::separator{border-top:1 solid #161616;height:0;margin:2 0}QMenu::icon{border-radius:2;margin:0 0 0 3;padding:1}QMenu::icon:checked{background-color:#5385a6}QMenu::indicator{margin-left:7}TPanelTitleBar{background-color:#262626;border-color:#161616;border-style:solid;border-width:0 0 1 0;height:20;min-height:20;qproperty-TitleColor:#7d7d7d;qproperty-ActiveTitleColor:#fff;qproperty-BorderPixmap:url('none');qproperty-ActiveBorderPixmap:url('../Default/imgs/white/none');qproperty-FloatBorderPixmap:url('none');qproperty-FloatActiveBorderPixmap:url('../Default/imgs/white/none')}QAbstractScrollArea::corner{background-color:#262626}QScrollBar{background-color:#262626;border:0}QScrollBar:horizontal{height:16;margin:0}QScrollBar:vertical{margin:0;width:16}QScrollBar::handle{border:1 solid #3a3a3a;border-radius:4}QScrollBar::handle:horizontal:hover,QScrollBar::handle:vertical:hover{background-color:#4f4f4f;border-color:#4f4f4f}QScrollBar::handle:horizontal:pressed,QScrollBar::handle:vertical:pressed{background-color:#636363;border-color:#636363}QScrollBar::handle:horizontal{background-color:#3a3a3a;margin:3 16;min-width:20}QScrollBar::handle:vertical{background-color:#3a3a3a;margin:16 3;min-height:20}QScrollBar::add-line{subcontrol-origin:margin;border:0}QScrollBar::add-line:horizontal{subcontrol-position:right;background-color:#262626;margin:0;width:16}QScrollBar::add-line:vertical{subcontrol-position:bottom;background-color:#262626;margin:0;height:16}QScrollBar::sub-line{border:0;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{subcontrol-position:left;background-color:#262626;margin:0;width:16}QScrollBar::sub-line:vertical{subcontrol-position:top;background-color:#262626;margin:0;height:16}QScrollBar::up-arrow:vertical{image:url('../Default/imgs/white/scroll-up.svg');image-position:center center}QScrollBar::up-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::down-arrow:vertical{image:url('../Default/imgs/white/scroll-down.svg');image-position:center center}QScrollBar::down-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::left-arrow:horizontal{image:url('../Default/imgs/white/scroll-left.svg');image-position:center center}QScrollBar::left-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::right-arrow:horizontal{image:url('../Default/imgs/white/scroll-right.svg');image-position:center center}QScrollBar::right-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::sub-page:horizontal,QScrollBar::add-page:horizontal,QScrollBar::sub-page:vertical,QScrollBar::add-page:vertical{background:none}QToolBar{padding:0}QToolBar::separator:horizontal{border-left:1 solid #161616;margin:0 1;width:0}QToolBar::separator:vertical{border-top:1 solid #161616;height:0;margin:1 0}QToolBar QLabel{margin-top:1}QToolBar QToolBar{border:0}QToolButton::menu-indicator{image:none}QToolButton::menu-button{border-image:none}.DvScrollWidget QPushButton,DvScrollWidget QPushButton,#ScrollLeftButton QPushButton,#ScrollRightButton QPushButton,#ScrollUpButton QPushButton,#ScrollDownButton QPushButton{background-color:#515151;border:0 solid red;border-radius:0;padding:0;max-width:16}.DvScrollWidget QPushButton:hover,DvScrollWidget QPushButton:hover,#ScrollLeftButton QPushButton:hover,#ScrollRightButton QPushButton:hover,#ScrollUpButton QPushButton:hover,#ScrollDownButton QPushButton:hover{background-color:#5e5e5e}.DvScrollWidget QPushButton:pressed,DvScrollWidget QPushButton:pressed,#ScrollLeftButton QPushButton:pressed,#ScrollRightButton QPushButton:pressed,#ScrollUpButton QPushButton:pressed,#ScrollDownButton QPushButton:pressed{background-color:#191919}#ScrollLeftButton,#ScrollRightButton,#ScrollUpButton,#ScrollDownButton{margin:0;min-width:16}#ScrollLeftButton{border-right:1 solid #161616;image:url('../Default/imgs/white/scroll-left.svg')}#ScrollRightButton{border-left:1 solid #161616;margin-left:3;image:url('../Default/imgs/white/scroll-right.svg')}#ScrollUpButton{image:url('../Default/imgs/white/scroll-up.svg')}#ScrollDownButton{image:url('../Default/imgs/white/scroll-down.svg')}#keyFrameNavigator{background:none;margin:0;padding:0}#keyFrameNavigator QToolButton{min-width:18}#keyFrameNavigator #PreviousKey{image:url('../Default/imgs/white/prevkey.svg')}#keyFrameNavigator #PreviousKey:hover{image:url('../Default/imgs/white/prevkey_over.svg')}#keyFrameNavigator #PreviousKey:disabled{image:url('../Default/imgs/white/prevkey_disabled.svg')}#keyFrameNavigator #NextKey{image:url('../Default/imgs/white/nextkey.svg')}#keyFrameNavigator #NextKey:hover{image:url('../Default/imgs/white/nextkey_over.svg')}#keyFrameNavigator #NextKey:disabled{image:url('../Default/imgs/white/nextkey_disabled.svg')}.treeview,QTreeWidget,QTreeView,#FunctionEditorTree{background-color:#262626;alternate-background-color:#2b2b2b;border:0;margin:0;outline:0}.treeview::item:selected,QTreeWidget::item:selected,QTreeView::item:selected,#FunctionEditorTree::item:selected{background-color:#5385a6;color:#fff}.treeview::branch:adjoins-item,QTreeWidget::branch:adjoins-item,QTreeView::branch:adjoins-item,#FunctionEditorTree::branch:adjoins-item{border-image:url('')}.treeview::branch:has-siblings,QTreeWidget::branch:has-siblings,QTreeView::branch:has-siblings,#FunctionEditorTree::branch:has-siblings{border-image:url('')}.treeview::branch:has-siblings:adjoins-item,QTreeWidget::branch:has-siblings:adjoins-item,QTreeView::branch:has-siblings:adjoins-item,#FunctionEditorTree::branch:has-siblings:adjoins-item{border-image:url('')}.treeview::branch:has-children:closed,QTreeWidget::branch:has-children:closed,QTreeView::branch:has-children:closed,#FunctionEditorTree::branch:has-children:closed{background:url('../Default/imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:open,QTreeWidget::branch:has-children:open,QTreeView::branch:has-children:open,#FunctionEditorTree::branch:has-children:open{background:url('../Default/imgs/white/treebranch-open.svg') no-repeat;background-position:center center;image:none}.treeview::branch:has-children:has-siblings:closed,QTreeWidget::branch:has-children:has-siblings:closed,QTreeView::branch:has-children:has-siblings:closed,#FunctionEditorTree::branch:has-children:has-siblings:closed{background:url('../Default/imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:has-siblings:open,QTreeWidget::branch:has-children:has-siblings:open,QTreeView::branch:has-children:has-siblings:open,#FunctionEditorTree::branch:has-children:has-siblings:open{background:url('../Default/imgs/white/treebranch-open.svg') no-repeat;background-position:center center;border-image:none;image:none}QListView{outline:0;background:#262626;alternate-background-color:#2b2b2b}#TabBarContainer{background-color:#262626}.Button,QPushButton,.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{background-color:#515151;border:1 solid #303030;border-radius:2;color:#dbdbdb;margin:0;padding:3 15}.Button:hover,QPushButton:hover,.ComboBox:hover,#ViewerFpsSlider::sub-line:horizontal:hover,#ViewerFpsSlider::add-line:horizontal:hover,QComboBox:hover{background-color:#5e5e5e;border-color:#303030;color:#dbdbdb}.Button:pressed,QPushButton:pressed,#ViewerFpsSlider::sub-line:horizontal:pressed,#ViewerFpsSlider::add-line:horizontal:pressed{background-color:#191919;border-color:#141414;color:#dbdbdb}.Button:checked,QPushButton:checked{background-color:#191919;border-color:#141414;color:#dbdbdb}.Button:checked:hover,QPushButton:checked:hover{background-color:#1e1e1e}.Button:checked:hover:pressed,QPushButton:checked:hover:pressed{background:#191919}.Button:disabled,QPushButton:disabled,.ComboBox:disabled,#ViewerFpsSlider::sub-line:horizontal:disabled,#ViewerFpsSlider::add-line:horizontal:disabled,QComboBox:disabled{background-color:#3d3d3d;border-color:#303030;color:#808080}#PushButton_NoPadding{padding:3}.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{padding:1 0 1 4;margin:1 0}.ComboBox::drop-down,QComboBox::drop-down{image:url('../Default/imgs/white/combo_downarrow.svg');image-position:center center;width:16}.ComboBox::drop-down:disabled,QComboBox::drop-down:disabled{image:url('../Default/imgs/white/combo_downarrow_disabled.svg')}.ComboBox QAbstractItemView,QComboBox QAbstractItemView{background-color:#303030;border:1 solid #161616;selection-background-color:#5385a6;selection-color:#fff}.LineEdit,QLineEdit,#TaskSheetItem,#tasksRemoveBox,#tasksAddBox{background-color:#1c1c1c;border:1 solid #3d3d3d;border-radius:2;color:#cecece;selection-background-color:#5385a6;selection-color:#fff;padding:0 0 0 1}.LineEdit:focus,QLineEdit:focus,#TaskSheetItem:focus,#tasksRemoveBox:focus,#tasksAddBox:focus{background-color:#1c1c1c;border-color:#5385a6;color:#cecece}.LineEdit:disabled,QLineEdit:disabled,#TaskSheetItem:disabled,#tasksRemoveBox:disabled,#tasksAddBox:disabled{background-color:#262626;border-color:#363636;color:#808080}.CheckBox,QCheckBox{color:#cecece}.CheckBox:hover,QCheckBox:hover,.RadioButton:hover,QRadioButton:hover{color:#fff}.CheckBox:disabled,QCheckBox:disabled{color:#808080}.CheckBox::indicator,QMenu::indicator,QCheckBox::indicator,.GroupBox::indicator,QGroupBox::indicator{background-color:#1c1c1c;border:1 solid #3d3d3d;border-radius:2;height:9;padding:1;width:9}.CheckBox::indicator:hover,QMenu::indicator:hover,.CheckBox::indicator:checked:hover,QCheckBox::indicator:hover,.GroupBox::indicator:hover,QMenu::indicator:checked:hover,QCheckBox::indicator:checked:hover,.GroupBox::indicator:checked:hover,QGroupBox::indicator:hover,QGroupBox::indicator:checked:hover{background-color:#1c1c1c;border-color:#5385a6}.CheckBox::indicator:checked,QMenu::indicator:checked,QCheckBox::indicator:checked,.GroupBox::indicator:checked,QGroupBox::indicator:checked{background-color:#1c1c1c;border-color:#3d3d3d;image:url('../Default/imgs/white/checkmark.svg')}.CheckBox::indicator:checked:disabled,QMenu::indicator:checked:disabled,QCheckBox::indicator:checked:disabled,.GroupBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled{background-color:#262626;border-color:#191919;image:url('../Default/imgs/white/checkmark_disabled.svg')}.CheckBox::indicator:disabled,QMenu::indicator:disabled,QCheckBox::indicator:disabled,.GroupBox::indicator:disabled,QGroupBox::indicator:disabled{background-color:#262626;border-color:#191919}.RadioButton::indicator:unchecked,QRadioButton::indicator:unchecked,#CameraSettingsRadioButton_Small::indicator:unchecked{image:url('../Default/imgs/white/radiobutton_unchecked.svg');image-position:center center}.RadioButton::indicator:checked,QRadioButton::indicator:checked,#CameraSettingsRadioButton_Small::indicator:checked{image:url('../Default/imgs/white/radiobutton_checked.svg');image-position:center center}.GroupBox,QGroupBox{margin:6 0 0 0;padding:5 0}.GroupBox::title,QGroupBox::title{subcontrol-origin:margin;left:15;margin:-3 0 0 0;padding:0 3}.GroupBox::title:hover,QGroupBox::title:hover{color:#fff}.GroupBox::title:disabled,QGroupBox::title:disabled{color:#808080}.GroupBox::indicator,QGroupBox::indicator{subcontrol-origin:margin;margin-top:2}.GroupBox:disabled,QGroupBox:disabled{color:#808080}.Slider::groove:horizontal,QSlider::groove:horizontal{background-color:transparent;background-image:url('../Default/imgs/white/slider-groove_dark.svg');background-position:center center;background-repeat:repeat-x;margin:0;height:20;min-height:20}.Slider::groove:horizontal:disabled,QSlider::groove:horizontal:disabled{background-image:url('../Default/imgs/white/slider-groove_disabled_dark.svg')}.Slider::handle:horizontal,QSlider::handle:horizontal{width:10;margin:-2 -1;image:url('../Default/imgs/white/slider-handle.svg')}.Slider::handle:horizontal:disabled,QSlider::handle:horizontal:disabled{image:url('../Default/imgs/white/slider-handle_disabled.svg')}#IntPairField,#DoublePairField{qproperty-LightLineColor:#191919;qproperty-LightLineEdgeColor:#191919;qproperty-DarkLineColor:#191919;qproperty-MiddleLineColor:#191919;qproperty-HandleLeftPixmap:url("../Default/imgs/white/slider-handle.svg");qproperty-HandleRightPixmap:url("../Default/imgs/white/slider-handle.svg");qproperty-HandleLeftGrayPixmap:url("../Default/imgs/white/slider-handle_disabled.svg");qproperty-HandleRightGrayPixmap:url("../Default/imgs/white/slider-handle_disabled.svg")}#DirTreeView{background-color:#262626;alternate-background-color:#262626;border:1 solid #161616;border-right:0}DvItemViewerPanel{qproperty-TextColor:#cecece;qproperty-AlternateBackground:#282828;qproperty-SelectedTextColor:#fff;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedItemBackground:#5385a6}#FileBrowser DvItemViewerPanel,#SceneCast DvItemViewerPanel{background-color:#303030}#FileBrowser #castFrame,#SceneCast #castFrame{border-top:1 solid #161616;border-right:1 solid #161616;border-bottom:1 solid #161616;margin:0}#FileBrowser QToolButton,#SceneCast QToolButton{padding:1}DvDirTreeView{qproperty-TextColor:#cecece;qproperty-SelectedTextColor:#fff;qproperty-SelectedItemBackground:#5385a6;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedFolderTextColor:#fff;alternate-background-color:#2b2b2b;background-color:#262626;border:1 solid #161616}#FileDoesNotExistLabel{color:#f00}#SceneCast QToolBar{border-top:1 solid #161616}#SceneCast QToolButton{margin:3 1 2 1;padding:1}#CastBrowser{border:0;margin:0}#FilmStrip QComboBox{border-radius:0;border-width:0}#FilmStrip QComboBox QAbstractItemView{background-color:#303030}#CleanupSettings #CleanupSettingsFrame{margin-top:2;margin-bottom:4}#CleanupSettings QGroupBox{margin-bottom:3}ParamsPage{qproperty-TextColor:#cecece}#CameraSettingsButton{padding:2}#CameraSettingsRadioButton:hover{background:none}#CameraSettingsRadioButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#CameraSettingsRadioButton::indicator:unchecked{image:url('../Default/imgs/white/lock_off.svg')}#CameraSettingsRadioButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('../Default/imgs/white/lock_on.svg')}#CameraSettingsRadioButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#CameraSettingsDPI{color:#9fdaff}#CameraSettingsRadioButton_Small{padding:0}#CameraSettingsRadioButton_Small::indicator{background-color:transparent;border:0;height:21;margin:0;width:11}#ForceSquaredPixelButton{height:16;border:1 solid rgba(255,255,255,0);image:url('../Default/imgs/white/fsp_unchecked.svg');padding:2;width:16;margin:0}#ForceSquaredPixelButton:checked{image:url('../Default/imgs/white/fsp_checked.svg')}#OutputSettingsLabel{color:#9fdaff}PencilTestPopup{min-height:730px;min-width:512px}#MatchLineButton{background-color:#565656}#MatchLineButton:checked{background-color:#7d7d7d;border:2 solid #5385a6;border-radius:2}#LargeSizedText{font-size:17}#StartupLabel{padding:3}#StartupLabel:hover{background:#4a4a4a}QStatusBar{background-color:#c0c0c0}QStatusBar::item{border:0}QStatusBar QLabel{background-color:#c0c0c0}QStatusBar #StatusBarLabel{background-color:#fff;padding:1 3}#TitleTxtLabel{color:#9fdaff}#StyleEditor QPushButton{margin:2 1;padding:0}#StyleEditor #TabBarContainer{margin-left:-4}#StyleEditor #bottomWidget{border-top:1 solid #161616;padding:3 2 8 3}#StyleEditor #bottomWidget QPushButton{padding:3 5}#StyleEditorTabBar::tab::first{border-left:1 solid #161616}#HexagonalColorWheel{qproperty-BGColor:#303030}#colorSlider::groove:horizontal{height:1;border-image:none}#colorSlider::handle:horizontal{width:8;margin:-8 -4}#colorSliderAddButton,#colorSliderSubButton{background:none;border-color:transparent;image-position:center center;min-height:16;padding:0;min-width:18}#colorSliderAddButton{image:url('../Default/imgs/white/scroll-right.svg')}#colorSliderSubButton{image:url('../Default/imgs/white/scroll-left.svg')}#PlainColorPageParts{border-bottom:1 solid #161616}#PlainColorPageParts QLineEdit{max-width:35}PaletteViewer DvScrollWidget QPushButton{border-top:0;margin-bottom:1;max-width:15;min-width:15}PaletteViewer DvScrollWidget #ScrollLeftButton{border-radius:0;margin-bottom:1;max-width:16;min-width:16}PaletteViewer DvScrollWidget #ScrollRightButton{border-radius:0;margin-left:1;margin-bottom:1;max-width:16;min-width:16}PaletteViewer QToolBar{background:none;border-bottom:1 solid #161616;padding:0;margin:0}PaletteViewer QToolBar::separator:horizontal{margin:0}PaletteViewer QToolBar QToolButton{margin:0 0 1 0;padding:1 0 2 0}#PageViewer{qproperty-TextColor:#cecece}#PaletteLockButton{border-radius:0;margin:0 0 1 1}#PaletteLockButton:checked{background-color:#C34040;border-color:#C34040}#PaletteLockButton:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#WordButton{padding-right:0;padding-left:0}QDialog{background-color:#303030}QDialog #dialogButtonFrame{background-color:#282828;border-top:1 solid #161616}QDialog #dialogButtonFrame QPushButton{border-color:#282828;outline:0}QDialog #dialogButtonFrame QPushButton:focus{background-color:#5385a6;border-color:#282828;color:#f4f4f4}QDialog #dialogButtonFrame QPushButton:focus:hover{background-color:#6c98b6}QDialog #dialogButtonFrame QPushButton:focus:pressed{background-color:#191919;border-color:#141414;color:#dbdbdb}#SceneSettings QLabel{color:#9fdaff}#PreferencesPopup QListWidget{background-color:#262626;alternate-background-color:#262626;border:1 solid #161616;font-size:13}#PreferencesPopup QListWidget::item{border:0;padding:3}#PreferencesPopup QListWidget::item:hover{color:#cecece;background-color:rgba(255,255,255,0.15)}#PreferencesPopup QListWidget::item:selected{background-color:#5385a6;color:#fff}#ShortcutTree{border:1 solid #161616}#ShortcutTree::item{padding:1 0}#ShortcutTree QScrollBar:vertical{width:16;margin-right:-1}ProjectPopup QLabel{color:#9fdaff}#GearButton{qproperty-icon:url('../Default/imgs/white/gear.svg')}#SubfolderButton{qproperty-icon:url('../Default/imgs/white/subfolder.svg')}SchematicViewer{qproperty-TextColor:#cecece;qproperty-VerticalLineColor:#090909;qproperty-LevelColumnColor:#4C6E4C;qproperty-VectorColumnColor:#7B7B4C;qproperty-ChildColumnColor:#6A526B;qproperty-FullcolorColumnColor:#657A96;qproperty-FxColumnColor:#56553C;qproperty-PaletteColumnColor:#3A655F;qproperty-MeshColumnColor:#684D86;qproperty-TableColor:#62628c;qproperty-ActiveCameraColor:#2d7dca;qproperty-OtherCameraColor:#6c797b;qproperty-GroupColor:#3b6e9c;qproperty-PegColor:#9f6e3c;qproperty-SplineColor:#6a9d1c;qproperty-ActiveOutputColor:#2d7dca;qproperty-OtherOutputColor:#6c797b;qproperty-XsheetColor:#62628c;qproperty-NormalFxColor:#6a7e96;qproperty-MacroFxColor:#815c79;qproperty-ImageAdjustFxColor:#656287;qproperty-LayerBlendingFxColor:#4f757d;qproperty-MatteFxColor:#ae7171;qproperty-SchematicPreviewButtonBgOnColor:#c8c864;qproperty-SchematicPreviewButtonOnImage:url('../Default/imgs/white/x_prev_eye_on.svg');qproperty-SchematicPreviewButtonBgOffColor:rgba(200,200,100,0.5);qproperty-SchematicPreviewButtonOffImage:url('../Default/imgs/white/x_prev_eye_off.svg');qproperty-SchematicCamstandButtonBgOnColor:#eb906b;qproperty-SchematicCamstandButtonOnImage:url('../Default/imgs/white/x_table_view_on.svg');qproperty-SchematicCamstandButtonTranspImage:url('../Default/imgs/white/x_table_view_transp.svg');qproperty-SchematicCamstandButtonBgOffColor:rgba(235,144,107,0.5);qproperty-SchematicCamstandButtonOffImage:url('../Default/imgs/white/x_table_view_off.svg')}#SchematicBottomFrame{background-color:#303030;border:0;margin:0;padding:0}#SchematicBottomFrame QToolBar::separator:horizontal{margin:0}#SchematicBottomFrame QToolBar QToolButton{padding:0;margin:2}#SchematicSceneViewer{background-color:#232323;border-bottom:1 solid #161616}#FxSettingsTabBar::tab{border-top:1 solid #161616}#FxSettingsTabBar::tab::first,#FxSettingsTabBar::tab::only-one{border-left:1 solid #161616}FxSettings QToolBar{border-top:1 solid #161616;border-right:1 solid #161616;border-left:1 solid #161616;min-height:23;padding:3 0}FxSettings QToolBar QToolBar{border:0}#FxSettingsLabel{color:#a0e680}#FxSettingsHelpButton{background-color:#80a0dc;color:#000;padding-top:0;padding-bottom:0}#FxSettingsHelpButton:hover{background-color:#a8bee7}#ScriptConsole{font-family:'Courier New',monospace;border:0;color:#000000;padding:3}#ScriptConsole QFrame{background-color:#dcdcdc}#ScriptConsole TPanelTitleBar{background-color:#262626}#TaskSheetItemLabel{color:#cecece}#Tasks QToolBar{border-bottom:1 solid #161616;margin:0;padding:0}#Tasks QToolBar QToolButton{margin:2 2 3 2}#ToolBar QToolBar{padding-left:2}#ToolOptions TPanelTitleBar{border-right:1 solid #161616;border-bottom:0}#CommandBar TPanelTitleBar{border-right:1 solid #161616;border-bottom:0}IconViewField{qproperty-ThicknessPixmap:url("../Default/imgs/white/selectiontool_thickness.svg")}#EditToolLockButton{spacing:0}#EditToolLockButton:hover{background:none}#EditToolLockButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#EditToolLockButton::indicator:unchecked{image:url('../Default/imgs/white/lock_off.svg')}#EditToolLockButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('../Default/imgs/white/lock_on.svg')}#EditToolLockButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}PopupButton::menu-indicator{border-left:0;height:17;image:url('../Default/imgs/white/combo_downarrow.svg');width:10}PopupButton::menu-indicator:hover{image:url('../Default/imgs/white/combo_downarrow.svg')}PopupButton::menu-indicator:disabled{image:url('../Default/imgs/white/combo_downarrow_disabled.svg')}#Cap,#Join{padding:0 4 0 -8;max-width:32;min-width:32}#Cap QMenu,#Join QMenu{max-width:28;min-width:28}#Cap QMenu::item,#Join QMenu::item{max-width:28;min-width:28;padding:0}QToolBar#MediumPaddingToolBar QToolButton{padding-left:3;padding-right:3}QToolBar#WidePaddingToolBar QToolButton{padding-left:6;padding-right:6}#CommandBar{margin:0;padding:0;border:0}#CommandBar::separator:horizontal{margin-right:3;margin-left:3}#expandButton:checked{background-color:transparent;border-color:transparent;color:#cecece}#expandButton:checked:hover{background-color:#5e5e5e;border-color:#5e5e5e}#expandButton:checked:pressed{background-color:#191919;border-color:#141414}#ComboViewerPanel Toolbar{border-bottom:1 solid #161616}#ComboViewerPanel Toolbar::separator:horizontal{margin:0 0 0 2}#ComboViewerPanel Toolbar QToolButton{margin:2 0 3 2}#ComboViewerToolOptions{border-bottom:1 solid #161616}#ComboViewer #ToolBarContainer,#ViewerPanel #ToolBarContainer,FlipBook #ToolBarContainer{background-color:transparent;border-top:2 solid #161616;border-bottom:1 solid #161616;padding-right:-1}#flipCustomize{margin-left:3}#flipCustomize::menu-button{background-color:transparent;width:35}#flipCustomize::menu-arrow{image:none}QToolBar#FlipConsolePlayToolBar::separator:horizontal{margin:0 3}QToolBar#FlipConsolePlayToolBar QToolButton{margin-top:2;margin-bottom:2;height:16;padding-left:1;padding-right:1}#ViewerFpsSlider{background-color:transparent;background-image:url('../Default/imgs/white/slider-groove_dark.svg');background-position:center center;background-repeat:repeat-x;border:0;height:19;margin:0 3 0 37;max-width:300;min-width:0}#ViewerFpsSlider::sub-line:horizontal{subcontrol-origin:absolute;background-color:#515151;border:1 solid #303030;border-top-left-radius:2;border-bottom-left-radius:2;height:16;left:-33;width:14}#ViewerFpsSlider::add-line:horizontal{subcontrol-position:left;background-color:#515151;border:1 solid #303030;border-top-right-radius:2;border-bottom-right-radius:2;left:18;height:16;image-position:center center;width:13}#ViewerFpsSlider::handle::horizontal{background-color:#898989;border:1 solid #898989;border-radius:2;margin:2 0 3 0;min-width:9;width:9;max-width:9}FlipSlider{qproperty-PBHeight:15;qproperty-PBOverlay:url('../Default/imgs/white/flipslider_dark.svg');qproperty-PBColorMarginLeft:1;qproperty-PBColorMarginTop:2;qproperty-PBColorMarginRight:1;qproperty-PBColorMarginBottom:2;qproperty-PBMarker:url('../Default/imgs/white/flipmarker_dark.svg');qproperty-PBMarkerMarginLeft:3;qproperty-PBMarkerMarginRight:3;qproperty-notStartedColor:rgba(205,101,101,0.78);qproperty-startedColor:#1abc3f;qproperty-baseColor:#1c1c1c;qproperty-finishedColor:#1c1c1c}Ruler{qproperty-ParentBGColor:#303030;qproperty-ScaleColor:#cecece}#RulerToolOptionValues{color:#000}#xsheetArea,#ScrollArea{background-color:#1c1c1c;border:0}#xsheetScrollArea{border:0}#cornerWidget QToolButton{padding:0}#xsheetColumnAreaMenu_Preview{background-color:#E6E678}#xsheetColumnAreaMenu_Lock{background-color:#F5F5F5}#xsheetColumnAreaMenu_Camstand{background-color:#FFA480}#xsheetColumnAreaMenu_Preview,#xsheetColumnAreaMenu_Lock,#xsheetColumnAreaMenu_Camstand{color:#000}#noteTextEdit{color:#000}XsheetViewer{qproperty-TextColor:#cecece;qproperty-BGColor:#282828;qproperty-LightLineColor:#1f1f1f;qproperty-MarkerLineColor:#1E96C4;qproperty-VerticalLineColor:#090909;qproperty-VerticalLineHeadColor:#686868;qproperty-PreviewFrameTextColor:#9fdaff;qproperty-CurrentRowBgColor:#506082;qproperty-EmptyColumnHeadColor:#444;qproperty-SelectedColumnTextColor:#E66464;qproperty-EmptyCellColor:#303030;qproperty-NotEmptyColumnColor:#383838;qproperty-SelectedEmptyCellColor:#545454;qproperty-LevelColumnColor:#4C6E4C;qproperty-LevelColumnBorderColor:#8FB38F;qproperty-SelectedLevelColumnColor:#678667;qproperty-VectorColumnColor:#7B7B4C;qproperty-VectorColumnBorderColor:#BBBB9A;qproperty-SelectedVectorColumnColor:#949466;qproperty-ChildColumnColor:#6A526B;qproperty-ChildColumnBorderColor:#B1A3B3;qproperty-SelectedChildColumnColor:#816e82;qproperty-FullcolorColumnColor:#657A96;qproperty-FullcolorColumnBorderColor:#9EB8BB;qproperty-SelectedFullcolorColumnColor:#8895a6;qproperty-FxColumnColor:#56553C;qproperty-FxColumnBorderColor:#95958A;qproperty-SelectedFxColumnColor:#6f6e56;qproperty-ReferenceColumnColor:#616161;qproperty-ReferenceColumnBorderColor:#A2A2A2;qproperty-SelectedReferenceColumnColor:#7a7a7a;qproperty-PaletteColumnColor:#3A655F;qproperty-PaletteColumnBorderColor:#86ACA7;qproperty-SelectedPaletteColumnColor:#52807a;qproperty-MeshColumnColor:#684D86;qproperty-MeshColumnBorderColor:#BA92EF;qproperty-SelectedMeshColumnColor:#82689e;qproperty-SoundTextColumnColor:#c8c8c8;qproperty-SoundTextColumnBorderColor:#8c8c8c;qproperty-SelectedSoundTextColumnColor:#e2e2e2;qproperty-SoundColumnColor:#657456;qproperty-SoundColumnBorderColor:#A0AF7D;qproperty-SelectedSoundColumnColor:#7e8b72;qproperty-SoundColumnHlColor:#34FE5E;qproperty-SoundColumnTrackColor:#B6C29D;qproperty-ColumnHeadPastelizer:#000;qproperty-SelectedColumnHead:#506082;qproperty-LightLightBGColor:#303030;qproperty-LightBGColor:#d8d8d8;qproperty-DarkBGColor:#c9c9c9;qproperty-DarkLineColor:#7e7e7e;qproperty-XsheetColumnNameBgColor:rgba(0,0,0,0);qproperty-XsheetDragBarHighlightColor:rgba(255,255,255,0.5);qproperty-XsheetPreviewButtonBgOnColor:#c8c864;qproperty-XsheetPreviewButtonOnImage:url('../Default/imgs/white/x_prev_eye_on.svg');qproperty-XsheetPreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetPreviewButtonOffImage:url('../Default/imgs/white/x_prev_eye_off.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');qproperty-XsheetCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetCamstandButtonOffImage:url('../Default/imgs/white/x_table_view_off.svg');qproperty-XsheetLockButtonBgOnColor:rgba(255,255,255,0.3);qproperty-XsheetLockButtonOnImage:url('../Default/imgs/white/x_lock_on.svg');qproperty-XsheetLockButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetLockButtonOffImage:url('../Default/imgs/white/x_lock_off.svg');qproperty-XsheetConfigButtonBgColor:rgba(255,255,255,0);qproperty-XsheetConfigButtonImage:url('../Default/imgs/white/x_config.svg');qproperty-TimelinePreviewButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelinePreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineCamstandButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelineCamstandButtonTranspImage:url('../Default/imgs/white/timeline_toggle_transp.svg');qproperty-TimelineCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineLockButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelineLockButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineConfigButtonBgColor:rgba(255,255,255,0);qproperty-TimelineConfigButtonImage:url('../Default/imgs/white/timeline_config.svg');qproperty-LayerHeaderPreviewImage:url('../Default/imgs/white/layer_header_prev_eye.svg');qproperty-LayerHeaderPreviewOverImage:url('../Default/imgs/white/layer_header_prev_eye_over.svg');qproperty-LayerHeaderCamstandImage:url('../Default/imgs/white/layer_header_table_view.svg');qproperty-LayerHeaderCamstandOverImage:url('../Default/imgs/white/layer_header_table_view_over.svg');qproperty-LayerHeaderLockImage:url('../Default/imgs/white/lock_on.svg');qproperty-LayerHeaderLockOverImage:url('../Default/imgs/white/lock_on_over.svg')}#XSheetToolbar{margin:0;padding:0;border:0}#XSheetToolbar QToolButton{padding:0;margin:4 1;min-height:19;height:19}#XSheetToolbar::separator:horizontal{margin:0 4}#FunctionEditor QToolBar{border-bottom:1 solid #161616}#FunctionEditor QToolBar QToolBar{border:0}#FunctionEditor QToolBar QLabel{margin-left:5}#FunctionEditor QToolBar QToolButton{height:18}#FunctionEditorTree{border-top:1 solid #161616}FunctionTreeView{qproperty-TextColor:#cecece;qproperty-CurrentTextColor:#E66464}FunctionPanel{qproperty-BGColor:#232323;qproperty-ValueLineColor:#161616;qproperty-FrameLineColor:#161616;qproperty-OtherCurvesColor:#707070;qproperty-RulerBackground:#1b1b1b;qproperty-TextColor:#cecece;qproperty-SubColor:#000;qproperty-SelectedColor:#FFA500}SpreadsheetViewer{qproperty-LightLightBGColor:#303030;qproperty-CurrentRowBgColor:#506082;qproperty-LightLineColor:#1f1f1f;qproperty-MarkerLineColor:#1E96C4;qproperty-BGColor:#383838;qproperty-VerticalLineColor:#090909;qproperty-KeyFrameColor:#995d1d;qproperty-KeyFrameBorderColor:#c9b04b;qproperty-SelectedKeyFrameColor:#be772b;qproperty-InBetweenColor:#666250;qproperty-InBetweenBorderColor:#cdcec8;qproperty-SelectedInBetweenColor:#7d7a6c;qproperty-SelectedEmptyColor:#545454;qproperty-SelectedSceneRangeEmptyColor:#5d5d5d;qproperty-TextColor:#cecece;qproperty-ColumnHeaderBorderColor:#686868;qproperty-SelectedColumnTextColor:#E66464}#ExpressionField{background-color:#cecece;border:1 solid #1b1b1b;margin:0}#FunctionSegmentViewerLinkButton{background-image:url('../Default/imgs/white/segment_unlinked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:hover{background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:checked{background-image:url('../Default/imgs/white/segment_linked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:disabled{background-image:url('../Default/imgs/white/segment_disabled.svg');background-repeat:no-repeat} \ No newline at end of file +.button-show,#LoadLevelShowButton,#CleanupSettingsShowButton,#OutputSettingsShowButton,#FxSettingsPreviewShowButton{image:url('../Default/imgs/white/plus.svg');image-position:center center;margin:0;padding:1;min-width:10;min-height:10}.button-show:checked,#LoadLevelShowButton:checked,#CleanupSettingsShowButton:checked,#OutputSettingsShowButton:checked,#FxSettingsPreviewShowButton:checked{background-color:#191919;border-color:#141414;image:url('../Default/imgs/white/minus.svg')}.button-show:checked:pressed,#LoadLevelShowButton:checked:pressed,#CleanupSettingsShowButton:checked:pressed,#OutputSettingsShowButton:checked:pressed,#FxSettingsPreviewShowButton:checked:pressed{background-color:#191919;border-color:#141414}.button-show:checked:hover,#LoadLevelShowButton:checked:hover,#CleanupSettingsShowButton:checked:hover,#OutputSettingsShowButton:checked:hover,#FxSettingsPreviewShowButton:checked:hover{background-color:#1e1e1e}.button-tool,QToolButton,#CameraSettingsRadioButton::indicator,#ForceSquaredPixelButton,#SchematicBottomFrame QToolBar QToolButton,#EditToolLockButton::indicator,#flipCustomize{background-color:rgba(255,255,255,0);border:1 solid rgba(255,255,255,0);border-radius:2;color:#dbdbdb;margin:1;padding:0}.button-tool:hover,QToolButton:hover,#CameraSettingsRadioButton::indicator:hover,#ForceSquaredPixelButton:hover,#colorSliderAddButton:hover,#colorSliderSubButton:hover,#SchematicBottomFrame QToolBar QToolButton:hover,#EditToolLockButton::indicator:hover,#flipCustomize:hover{background-color:#5e5e5e;border-color:#5e5e5e;color:#dbdbdb}.button-tool:pressed,QToolButton:pressed,#CameraSettingsRadioButton::indicator:pressed,#ForceSquaredPixelButton:pressed,#colorSliderAddButton:pressed,#colorSliderSubButton:pressed,#SchematicBottomFrame QToolBar QToolButton:pressed,#EditToolLockButton::indicator:pressed,#flipCustomize:pressed{background-color:#191919;border-color:#141414;color:#dbdbdb}.button-tool:checked,QToolButton:checked,#CameraSettingsRadioButton::indicator:checked,#ForceSquaredPixelButton:checked,#SchematicBottomFrame QToolBar QToolButton:checked,#EditToolLockButton::indicator:checked,#flipCustomize:checked{background-color:#5385a6;border-color:#5385a6;color:#fff}.button-tool:checked:hover,QToolButton:checked:hover,#CameraSettingsRadioButton::indicator:checked:hover,#ForceSquaredPixelButton:checked:hover,#SchematicBottomFrame QToolBar QToolButton:checked:hover,#EditToolLockButton::indicator:checked:hover,#flipCustomize:checked:hover{background-color:#6c98b6;border-color:#6c98b6}.button-tool:disabled,QToolButton:disabled,#CameraSettingsRadioButton::indicator:disabled,#ForceSquaredPixelButton:disabled,#SchematicBottomFrame QToolBar QToolButton:disabled,#EditToolLockButton::indicator:disabled,#flipCustomize:disabled{color:#808080}.button-flat,PaletteViewer QToolBar QToolButton{background-color:none;border:0;border-radius:0;margin:0}.button-flat:hover,PaletteViewer QToolBar QToolButton:hover{background-color:#5e5e5e}.button-flat:pressed,PaletteViewer QToolBar QToolButton:pressed{background-color:#161616}.frame,.GroupBox,#LoadLevelFrame,#PsdSettingsGroupBox,#CleanupSettingsFrame,#OutputSettingsBox,#OutputSettingsCameraBox,#SolidLineFrame,#FunctionParametersPanel,QGroupBox{border:1 solid #161616;border-radius:2}.tab-container,#TabBarContainer{background-color:transparent;qproperty-BottomAboveLineColor:#262626;qproperty-BottomBelowLineColor:#161616}.tab-flat,#StyleEditorTabBar::tab,#PaletteTabBar::tab,#FxSettingsTabBar::tab{background-color:#262626;border-right:1 solid #161616;border-bottom:1 solid #161616;color:#8b8b8b;padding:3 4 3 4}.tab-flat:hover,#StyleEditorTabBar::tab:hover,#PaletteTabBar::tab:hover,#FxSettingsTabBar::tab:hover{background-color:#303030;color:#8b8b8b}.tab-flat:selected,#StyleEditorTabBar::tab:selected,#PaletteTabBar::tab:selected,#FxSettingsTabBar::tab:selected{background-color:#303030;color:#f4f4f4;border-bottom-color:#303030}.tab-flat:only-one,#StyleEditorTabBar::tab:only-one,#PaletteTabBar::tab:only-one,#FxSettingsTabBar::tab:only-one{margin:0}.tab-round{background-color:#262626;border-top:1 solid #161616;border-right:1 solid #161616;border-left:1 solid #161616;border-bottom:1 solid #161616;color:#8b8b8b;margin:3 -1 0 0;padding:2 7 1 7}.tab-round:hover{background-color:#303030;color:#8b8b8b}.tab-round:selected{background-color:#303030;border-top-right-radius:2;border-top-left-radius:2;border-bottom-color:#303030;color:#f4f4f4;margin:1 -1 -1 0;padding:2 7 2 7}.tab-round:only-one{margin:1 0 0 0;padding:3 7 3 7}.tab-round:last{margin-right:0;border-top-right-radius:2}.tab-round:first{border-top-left-radius:2}QWidget{background-color:#303030;color:#cecece}QWidget:disabled{color:#808080}QFrame{border:0;margin:0;padding:0}QToolTip,#helpToolTip{background-color:#fff;border:1 solid #000;color:#000;padding:1 1}#DockSeparator,QMainWindow::separator,QSplitter::handle{background-color:#0c0c0c;height:4;width:4}#TDockPlaceholder{background-color:#F77272}TPanel{background-color:#0c0c0c}#TopBar{background:#303030;border:0;border-bottom:1 solid #161616;height:21}#TopBar #EditToolLockButton{background:#303030;spacing:0}#TopBar #EditToolLockButton::indicator{background:none;border:none;height:18;margin:1 2 0 0;padding-left:0;padding-right:0}#TopBarTabContainer{background-color:#303030;margin-bottom:1}#StackedMenuBar{border:0;margin:0;padding:0}QMenuBar{background-color:#303030;border:0}QMenuBar::item{background-color:#303030;border-left:1 solid #303030;margin:0;padding:3 5}QMenuBar::item:selected{background-color:rgba(255,255,255,0.15);color:#cecece}QMenuBar::item:pressed{background-color:#5385a6;color:#fff}#TopBarTab{margin:0;padding:0}#TopBarTab::tab{background-color:#262626;border-top:1 solid #161616;border-right:1 solid #161616;color:#8b8b8b;margin:0 0 0 0;padding:2 8 3 8}#TopBarTab::tab:hover{background-color:#303030;color:#8b8b8b}#TopBarTab::tab:selected{background-color:#303030;color:#f4f4f4}#TopBarTab::tab:first{border-left:1 solid #161616}#TopBarTab::tab:last{border-right:1 solid #161616}QMenu{background-color:#303030;border:1 solid #161616;padding:2 0}QMenu::item{padding:3 28}QMenu::item:selected{background-color:#5385a6;color:#fff}QMenu::item:checked{color:#cecece}QMenu::item:checked:selected{background-color:#5385a6;color:#fff}QMenu::item:disabled{background:none;color:#808080}QMenu::item:disabled:selected{border-color:transparent}QMenu::separator{border-top:1 solid #161616;height:0;margin:2 0}QMenu::icon{border-radius:2;margin:0 0 0 3;padding:1}QMenu::icon:checked{background-color:#5385a6}QMenu::indicator{margin-left:7}TPanelTitleBar{background-color:#262626;border-color:#161616;border-style:solid;border-width:0 0 1 0;height:20;min-height:20;qproperty-TitleColor:#7d7d7d;qproperty-ActiveTitleColor:#fff;qproperty-BorderPixmap:url('none');qproperty-ActiveBorderPixmap:url('../Default/imgs/white/none');qproperty-FloatBorderPixmap:url('none');qproperty-FloatActiveBorderPixmap:url('../Default/imgs/white/none')}QAbstractScrollArea::corner{background-color:#262626}QScrollBar{background-color:#262626;border:0}QScrollBar:horizontal{height:16;margin:0}QScrollBar:vertical{margin:0;width:16}QScrollBar::handle{border:1 solid #3a3a3a;border-radius:4}QScrollBar::handle:horizontal:hover,QScrollBar::handle:vertical:hover{background-color:#4f4f4f;border-color:#4f4f4f}QScrollBar::handle:horizontal:pressed,QScrollBar::handle:vertical:pressed{background-color:#636363;border-color:#636363}QScrollBar::handle:horizontal{background-color:#3a3a3a;margin:3 16;min-width:20}QScrollBar::handle:vertical{background-color:#3a3a3a;margin:16 3;min-height:20}QScrollBar::add-line{subcontrol-origin:margin;border:0}QScrollBar::add-line:horizontal{subcontrol-position:right;background-color:#262626;margin:0;width:16}QScrollBar::add-line:vertical{subcontrol-position:bottom;background-color:#262626;margin:0;height:16}QScrollBar::sub-line{border:0;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{subcontrol-position:left;background-color:#262626;margin:0;width:16}QScrollBar::sub-line:vertical{subcontrol-position:top;background-color:#262626;margin:0;height:16}QScrollBar::up-arrow:vertical{image:url('../Default/imgs/white/scroll-up.svg');image-position:center center}QScrollBar::up-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::down-arrow:vertical{image:url('../Default/imgs/white/scroll-down.svg');image-position:center center}QScrollBar::down-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::left-arrow:horizontal{image:url('../Default/imgs/white/scroll-left.svg');image-position:center center}QScrollBar::left-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::right-arrow:horizontal{image:url('../Default/imgs/white/scroll-right.svg');image-position:center center}QScrollBar::right-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::sub-page:horizontal,QScrollBar::add-page:horizontal,QScrollBar::sub-page:vertical,QScrollBar::add-page:vertical{background:none}QToolBar{padding:0}QToolBar::separator:horizontal{border-left:1 solid #161616;margin:0 1;width:0}QToolBar::separator:vertical{border-top:1 solid #161616;height:0;margin:1 0}QToolBar QLabel{margin-top:1}QToolBar QToolBar{border:0}QToolButton::menu-indicator{image:none}QToolButton::menu-button{border-image:none}.DvScrollWidget QPushButton,DvScrollWidget QPushButton,#ScrollLeftButton QPushButton,#ScrollRightButton QPushButton,#ScrollUpButton QPushButton,#ScrollDownButton QPushButton{background-color:#515151;border:0 solid red;border-radius:0;padding:0;max-width:16}.DvScrollWidget QPushButton:hover,DvScrollWidget QPushButton:hover,#ScrollLeftButton QPushButton:hover,#ScrollRightButton QPushButton:hover,#ScrollUpButton QPushButton:hover,#ScrollDownButton QPushButton:hover{background-color:#5e5e5e}.DvScrollWidget QPushButton:pressed,DvScrollWidget QPushButton:pressed,#ScrollLeftButton QPushButton:pressed,#ScrollRightButton QPushButton:pressed,#ScrollUpButton QPushButton:pressed,#ScrollDownButton QPushButton:pressed{background-color:#191919}#ScrollLeftButton,#ScrollRightButton,#ScrollUpButton,#ScrollDownButton{margin:0;min-width:16}#ScrollLeftButton{border-right:1 solid #161616;image:url('../Default/imgs/white/scroll-left.svg')}#ScrollRightButton{border-left:1 solid #161616;margin-left:3;image:url('../Default/imgs/white/scroll-right.svg')}#ScrollUpButton{image:url('../Default/imgs/white/scroll-up.svg')}#ScrollDownButton{image:url('../Default/imgs/white/scroll-down.svg')}#keyFrameNavigator{background:none;margin:0;padding:0}#keyFrameNavigator QToolButton{min-width:18}#keyFrameNavigator #PreviousKey{image:url('../Default/imgs/white/prevkey.svg')}#keyFrameNavigator #PreviousKey:hover{image:url('../Default/imgs/white/prevkey_over.svg')}#keyFrameNavigator #PreviousKey:disabled{image:url('../Default/imgs/white/prevkey_disabled.svg')}#keyFrameNavigator #NextKey{image:url('../Default/imgs/white/nextkey.svg')}#keyFrameNavigator #NextKey:hover{image:url('../Default/imgs/white/nextkey_over.svg')}#keyFrameNavigator #NextKey:disabled{image:url('../Default/imgs/white/nextkey_disabled.svg')}.treeview,QTreeWidget,QTreeView,#FunctionEditorTree{background-color:#262626;alternate-background-color:#2b2b2b;border:0;margin:0;outline:0}.treeview::item:selected,QTreeWidget::item:selected,QTreeView::item:selected,#FunctionEditorTree::item:selected{background-color:#5385a6;color:#fff}.treeview::branch:adjoins-item,QTreeWidget::branch:adjoins-item,QTreeView::branch:adjoins-item,#FunctionEditorTree::branch:adjoins-item{border-image:url('')}.treeview::branch:has-siblings,QTreeWidget::branch:has-siblings,QTreeView::branch:has-siblings,#FunctionEditorTree::branch:has-siblings{border-image:url('')}.treeview::branch:has-siblings:adjoins-item,QTreeWidget::branch:has-siblings:adjoins-item,QTreeView::branch:has-siblings:adjoins-item,#FunctionEditorTree::branch:has-siblings:adjoins-item{border-image:url('')}.treeview::branch:has-children:closed,QTreeWidget::branch:has-children:closed,QTreeView::branch:has-children:closed,#FunctionEditorTree::branch:has-children:closed{background:url('../Default/imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:open,QTreeWidget::branch:has-children:open,QTreeView::branch:has-children:open,#FunctionEditorTree::branch:has-children:open{background:url('../Default/imgs/white/treebranch-open.svg') no-repeat;background-position:center center;image:none}.treeview::branch:has-children:has-siblings:closed,QTreeWidget::branch:has-children:has-siblings:closed,QTreeView::branch:has-children:has-siblings:closed,#FunctionEditorTree::branch:has-children:has-siblings:closed{background:url('../Default/imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:has-siblings:open,QTreeWidget::branch:has-children:has-siblings:open,QTreeView::branch:has-children:has-siblings:open,#FunctionEditorTree::branch:has-children:has-siblings:open{background:url('../Default/imgs/white/treebranch-open.svg') no-repeat;background-position:center center;border-image:none;image:none}QListView{outline:0;background:#262626;alternate-background-color:#2b2b2b}#TabBarContainer{background-color:#262626}.Button,QPushButton,.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{background-color:#515151;border:1 solid #303030;border-radius:2;color:#dbdbdb;margin:0;padding:3 15}.Button:hover,QPushButton:hover,.ComboBox:hover,#ViewerFpsSlider::sub-line:horizontal:hover,#ViewerFpsSlider::add-line:horizontal:hover,QComboBox:hover{background-color:#5e5e5e;border-color:#303030;color:#dbdbdb}.Button:pressed,QPushButton:pressed,#ViewerFpsSlider::sub-line:horizontal:pressed,#ViewerFpsSlider::add-line:horizontal:pressed{background-color:#191919;border-color:#141414;color:#dbdbdb}.Button:checked,QPushButton:checked{background-color:#191919;border-color:#141414;color:#dbdbdb}.Button:checked:hover,QPushButton:checked:hover{background-color:#1e1e1e}.Button:checked:hover:pressed,QPushButton:checked:hover:pressed{background:#191919}.Button:disabled,QPushButton:disabled,.ComboBox:disabled,#ViewerFpsSlider::sub-line:horizontal:disabled,#ViewerFpsSlider::add-line:horizontal:disabled,QComboBox:disabled{background-color:#3d3d3d;border-color:#303030;color:#808080}#PushButton_NoPadding{padding:3}.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{padding:1 0 1 4;margin:1 0}.ComboBox::drop-down,QComboBox::drop-down{image:url('../Default/imgs/white/combo_downarrow.svg');image-position:center center;width:16}.ComboBox::drop-down:disabled,QComboBox::drop-down:disabled{image:url('../Default/imgs/white/combo_downarrow_disabled.svg')}.ComboBox QAbstractItemView,QComboBox QAbstractItemView{background-color:#303030;border:1 solid #161616;selection-background-color:#5385a6;selection-color:#fff}.LineEdit,QLineEdit,#TaskSheetItem,#tasksRemoveBox,#tasksAddBox{background-color:#1c1c1c;border:1 solid #3d3d3d;border-radius:2;color:#cecece;selection-background-color:#5385a6;selection-color:#fff;padding:0 0 0 1}.LineEdit:focus,QLineEdit:focus,#TaskSheetItem:focus,#tasksRemoveBox:focus,#tasksAddBox:focus{background-color:#1c1c1c;border-color:#5385a6;color:#cecece}.LineEdit:disabled,QLineEdit:disabled,#TaskSheetItem:disabled,#tasksRemoveBox:disabled,#tasksAddBox:disabled{background-color:#262626;border-color:#363636;color:#808080}.CheckBox,QCheckBox{color:#cecece}.CheckBox:hover,QCheckBox:hover,.RadioButton:hover,QRadioButton:hover{color:#fff}.CheckBox:disabled,QCheckBox:disabled{color:#808080}.CheckBox::indicator,QMenu::indicator,QCheckBox::indicator,.GroupBox::indicator,QGroupBox::indicator{background-color:#1c1c1c;border:1 solid #3d3d3d;border-radius:2;height:9;padding:1;width:9}.CheckBox::indicator:hover,QMenu::indicator:hover,.CheckBox::indicator:checked:hover,QCheckBox::indicator:hover,.GroupBox::indicator:hover,QMenu::indicator:checked:hover,QCheckBox::indicator:checked:hover,.GroupBox::indicator:checked:hover,QGroupBox::indicator:hover,QGroupBox::indicator:checked:hover{background-color:#1c1c1c;border-color:#5385a6}.CheckBox::indicator:checked,QMenu::indicator:checked,QCheckBox::indicator:checked,.GroupBox::indicator:checked,QGroupBox::indicator:checked{background-color:#1c1c1c;border-color:#3d3d3d;image:url('../Default/imgs/white/checkmark.svg')}.CheckBox::indicator:checked:disabled,QMenu::indicator:checked:disabled,QCheckBox::indicator:checked:disabled,.GroupBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled{background-color:#262626;border-color:#191919;image:url('../Default/imgs/white/checkmark_disabled.svg')}.CheckBox::indicator:disabled,QMenu::indicator:disabled,QCheckBox::indicator:disabled,.GroupBox::indicator:disabled,QGroupBox::indicator:disabled{background-color:#262626;border-color:#191919}.RadioButton::indicator:unchecked,QRadioButton::indicator:unchecked,#CameraSettingsRadioButton_Small::indicator:unchecked{image:url('../Default/imgs/white/radiobutton_unchecked.svg');image-position:center center}.RadioButton::indicator:checked,QRadioButton::indicator:checked,#CameraSettingsRadioButton_Small::indicator:checked{image:url('../Default/imgs/white/radiobutton_checked.svg');image-position:center center}.GroupBox,QGroupBox{margin:6 0 0 0;padding:5 0}.GroupBox::title,QGroupBox::title{subcontrol-origin:margin;left:15;margin:-3 0 0 0;padding:0 3}.GroupBox::title:hover,QGroupBox::title:hover{color:#fff}.GroupBox::title:disabled,QGroupBox::title:disabled{color:#808080}.GroupBox::indicator,QGroupBox::indicator{subcontrol-origin:margin;margin-top:2}.GroupBox:disabled,QGroupBox:disabled{color:#808080}.Slider::groove:horizontal,QSlider::groove:horizontal{background-color:transparent;background-image:url('../Default/imgs/white/slider-groove_dark.svg');background-position:center center;background-repeat:repeat-x;margin:0;height:20;min-height:20}.Slider::groove:horizontal:disabled,QSlider::groove:horizontal:disabled{background-image:url('../Default/imgs/white/slider-groove_disabled_dark.svg')}.Slider::handle:horizontal,QSlider::handle:horizontal{width:10;margin:-2 -1;image:url('../Default/imgs/white/slider-handle.svg')}.Slider::handle:horizontal:disabled,QSlider::handle:horizontal:disabled{image:url('../Default/imgs/white/slider-handle_disabled.svg')}#IntPairField,#DoublePairField{qproperty-LightLineColor:#191919;qproperty-LightLineEdgeColor:#191919;qproperty-DarkLineColor:#191919;qproperty-MiddleLineColor:#191919;qproperty-HandleLeftPixmap:url("../Default/imgs/white/slider-handle.svg");qproperty-HandleRightPixmap:url("../Default/imgs/white/slider-handle.svg");qproperty-HandleLeftGrayPixmap:url("../Default/imgs/white/slider-handle_disabled.svg");qproperty-HandleRightGrayPixmap:url("../Default/imgs/white/slider-handle_disabled.svg")}#DirTreeView{background-color:#262626;alternate-background-color:#262626;border:1 solid #161616;border-right:0}DvItemViewerPanel{qproperty-TextColor:#cecece;qproperty-AlternateBackground:#282828;qproperty-SelectedTextColor:#fff;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedItemBackground:#5385a6}#FileBrowser DvItemViewerPanel,#SceneCast DvItemViewerPanel{background-color:#303030}#FileBrowser #castFrame,#SceneCast #castFrame{border-top:1 solid #161616;border-right:1 solid #161616;border-bottom:1 solid #161616;margin:0}#FileBrowser QToolButton,#SceneCast QToolButton{padding:1}DvDirTreeView{qproperty-TextColor:#cecece;qproperty-SelectedTextColor:#fff;qproperty-SelectedItemBackground:#5385a6;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedFolderTextColor:#fff;alternate-background-color:#2b2b2b;background-color:#262626;border:1 solid #161616}#FileDoesNotExistLabel{color:#f00}#SceneCast QToolBar{border-top:1 solid #161616}#SceneCast QToolButton{margin:3 1 2 1;padding:1}#CastBrowser{border:0;margin:0}#FilmStrip QComboBox{border-radius:0;border-width:0}#FilmStrip QComboBox QAbstractItemView{background-color:#303030}#CleanupSettings #CleanupSettingsFrame{margin-top:2;margin-bottom:4}#CleanupSettings QGroupBox{margin-bottom:3}ParamsPage{qproperty-TextColor:#cecece}#CameraSettingsButton{padding:2}#CameraSettingsRadioButton:hover{background:none}#CameraSettingsRadioButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#CameraSettingsRadioButton::indicator:unchecked{image:url('../Default/imgs/white/lock_off.svg')}#CameraSettingsRadioButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('../Default/imgs/white/lock_on.svg')}#CameraSettingsRadioButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#CameraSettingsDPI{color:#9fdaff}#CameraSettingsRadioButton_Small{padding:0}#CameraSettingsRadioButton_Small::indicator{background-color:transparent;border:0;height:21;margin:0;width:11}#ForceSquaredPixelButton{height:16;border:1 solid rgba(255,255,255,0);image:url('../Default/imgs/white/fsp_unchecked.svg');padding:2;width:16;margin:0}#ForceSquaredPixelButton:checked{image:url('../Default/imgs/white/fsp_checked.svg')}#OutputSettingsLabel{color:#9fdaff}PencilTestPopup{min-height:730px;min-width:512px}#MatchLineButton{background-color:#565656}#MatchLineButton:checked{background-color:#7d7d7d;border:2 solid #5385a6;border-radius:2}#LargeSizedText{font-size:17}#StartupLabel{padding:3}#StartupLabel:hover{background:#4a4a4a}QStatusBar{background-color:#c0c0c0}QStatusBar::item{border:0}QStatusBar QLabel{background-color:#c0c0c0}QStatusBar #StatusBarLabel{background-color:#fff;padding:1 3}#TitleTxtLabel{color:#9fdaff}#StyleEditor QPushButton{margin:2 1;padding:0}#StyleEditor #TabBarContainer{margin-left:-4}#StyleEditor #bottomWidget{border-top:1 solid #161616;padding:3 2 8 3}#StyleEditor #bottomWidget QPushButton{padding:3 5}#StyleEditorTabBar::tab::first{border-left:1 solid #161616}#HexagonalColorWheel{qproperty-BGColor:#303030}#colorSlider::groove:horizontal{height:1;border-image:none}#colorSlider::handle:horizontal{width:8;margin:-8 -4}#colorSliderAddButton,#colorSliderSubButton{background:none;border-color:transparent;image-position:center center;min-height:16;padding:0;min-width:18}#colorSliderAddButton{image:url('../Default/imgs/white/scroll-right.svg')}#colorSliderSubButton{image:url('../Default/imgs/white/scroll-left.svg')}#PlainColorPageParts{border-bottom:1 solid #161616}#PlainColorPageParts QLineEdit{max-width:35}PaletteViewer DvScrollWidget QPushButton{border-top:0;margin-bottom:1;max-width:15;min-width:15}PaletteViewer DvScrollWidget #ScrollLeftButton{border-radius:0;margin-bottom:1;max-width:16;min-width:16}PaletteViewer DvScrollWidget #ScrollRightButton{border-radius:0;margin-left:1;margin-bottom:1;max-width:16;min-width:16}PaletteViewer QToolBar{background:none;border-bottom:1 solid #161616;padding:0;margin:0}PaletteViewer QToolBar::separator:horizontal{margin:0}PaletteViewer QToolBar QToolButton{margin:0 0 1 0;padding:1 0 2 0}#PageViewer{qproperty-TextColor:#cecece}#PaletteLockButton{border-radius:0;margin:0 0 1 1}#PaletteLockButton:checked{background-color:#C34040;border-color:#C34040}#PaletteLockButton:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#WordButton{padding-right:0;padding-left:0}QDialog{background-color:#303030}QDialog #dialogButtonFrame{background-color:#282828;border-top:1 solid #161616}QDialog #dialogButtonFrame QPushButton{border-color:#282828;outline:0}QDialog #dialogButtonFrame QPushButton:focus{background-color:#5385a6;border-color:#282828;color:#f4f4f4}QDialog #dialogButtonFrame QPushButton:focus:hover{background-color:#6c98b6}QDialog #dialogButtonFrame QPushButton:focus:pressed{background-color:#191919;border-color:#141414;color:#dbdbdb}#SceneSettings QLabel{color:#9fdaff}#PreferencesPopup QListWidget{background-color:#262626;alternate-background-color:#262626;border:1 solid #161616;font-size:13}#PreferencesPopup QListWidget::item{border:0;padding:3}#PreferencesPopup QListWidget::item:hover{color:#cecece;background-color:rgba(255,255,255,0.15)}#PreferencesPopup QListWidget::item:selected{background-color:#5385a6;color:#fff}#ShortcutTree{border:1 solid #161616}#ShortcutTree::item{padding:1 0}#ShortcutTree QScrollBar:vertical{width:16;margin-right:-1}ProjectPopup QLabel{color:#9fdaff}#GearButton{qproperty-icon:url('../Default/imgs/white/gear.svg')}#SubfolderButton{qproperty-icon:url('../Default/imgs/white/subfolder.svg')}SchematicViewer{qproperty-TextColor:#cecece;qproperty-VerticalLineColor:#090909;qproperty-LevelColumnColor:#4C6E4C;qproperty-VectorColumnColor:#7B7B4C;qproperty-ChildColumnColor:#6A526B;qproperty-FullcolorColumnColor:#657A96;qproperty-FxColumnColor:#56553C;qproperty-PaletteColumnColor:#3A655F;qproperty-MeshColumnColor:#684D86;qproperty-ReferenceColumnColor:#616161;qproperty-TableColor:#62628c;qproperty-ActiveCameraColor:#2d7dca;qproperty-OtherCameraColor:#6c797b;qproperty-GroupColor:#3b6e9c;qproperty-PegColor:#9f6e3c;qproperty-SplineColor:#6a9d1c;qproperty-ActiveOutputColor:#2d7dca;qproperty-OtherOutputColor:#6c797b;qproperty-XsheetColor:#62628c;qproperty-NormalFxColor:#6a7e96;qproperty-MacroFxColor:#815c79;qproperty-ImageAdjustFxColor:#656287;qproperty-LayerBlendingFxColor:#4f757d;qproperty-MatteFxColor:#ae7171;qproperty-SchematicPreviewButtonBgOnColor:#c8c864;qproperty-SchematicPreviewButtonOnImage:url('../Default/imgs/white/x_prev_eye_on.svg');qproperty-SchematicPreviewButtonBgOffColor:#616161;qproperty-SchematicPreviewButtonOffImage:url('../Default/imgs/white/x_prev_eye_off.svg');qproperty-SchematicCamstandButtonBgOnColor:#eb906b;qproperty-SchematicCamstandButtonOnImage:url('../Default/imgs/white/x_table_view_on.svg');qproperty-SchematicCamstandButtonTranspImage:url('../Default/imgs/white/x_table_view_transp.svg');qproperty-SchematicCamstandButtonBgOffColor:#616161;qproperty-SchematicCamstandButtonOffImage:url('../Default/imgs/white/x_table_view_off.svg')}#SchematicBottomFrame{background-color:#303030;border:0;margin:0;padding:0}#SchematicBottomFrame QToolBar::separator:horizontal{margin:0}#SchematicBottomFrame QToolBar QToolButton{padding:0;margin:2}#SchematicSceneViewer{background-color:#232323;border-bottom:1 solid #161616}#FxSettingsTabBar::tab{border-top:1 solid #161616}#FxSettingsTabBar::tab::first,#FxSettingsTabBar::tab::only-one{border-left:1 solid #161616}FxSettings QToolBar{border-top:1 solid #161616;border-right:1 solid #161616;border-left:1 solid #161616;min-height:23;padding:3 0}FxSettings QToolBar QToolBar{border:0}#FxSettingsLabel{color:#a0e680}#FxSettingsHelpButton{background-color:#80a0dc;color:#000;padding-top:0;padding-bottom:0}#FxSettingsHelpButton:hover{background-color:#a8bee7}#ScriptConsole{font-family:'Courier New',monospace;border:0;color:#000000;padding:3}#ScriptConsole QFrame{background-color:#dcdcdc}#ScriptConsole TPanelTitleBar{background-color:#262626}#TaskSheetItemLabel{color:#cecece}#Tasks QToolBar{border-bottom:1 solid #161616;margin:0;padding:0}#Tasks QToolBar QToolButton{margin:2 2 3 2}#ToolBar QToolBar{padding-left:2}#ToolOptions TPanelTitleBar{border-right:1 solid #161616;border-bottom:0}#CommandBar TPanelTitleBar{border-right:1 solid #161616;border-bottom:0}IconViewField{qproperty-ThicknessPixmap:url("../Default/imgs/white/selectiontool_thickness.svg")}#EditToolLockButton{spacing:0}#EditToolLockButton:hover{background:none}#EditToolLockButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#EditToolLockButton::indicator:unchecked{image:url('../Default/imgs/white/lock_off.svg')}#EditToolLockButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('../Default/imgs/white/lock_on.svg')}#EditToolLockButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}PopupButton::menu-indicator{border-left:0;height:17;image:url('../Default/imgs/white/combo_downarrow.svg');width:10}PopupButton::menu-indicator:hover{image:url('../Default/imgs/white/combo_downarrow.svg')}PopupButton::menu-indicator:disabled{image:url('../Default/imgs/white/combo_downarrow_disabled.svg')}#Cap,#Join{padding:0 4 0 -8;max-width:32;min-width:32}#Cap QMenu,#Join QMenu{max-width:28;min-width:28}#Cap QMenu::item,#Join QMenu::item{max-width:28;min-width:28;padding:0}QToolBar#MediumPaddingToolBar QToolButton{padding-left:3;padding-right:3}QToolBar#WidePaddingToolBar QToolButton{padding-left:6;padding-right:6}#CommandBar{margin:0;padding:0;border:0}#CommandBar::separator:horizontal{margin-right:3;margin-left:3}#expandButton:checked{background-color:transparent;border-color:transparent;color:#cecece}#expandButton:checked:hover{background-color:#5e5e5e;border-color:#5e5e5e}#expandButton:checked:pressed{background-color:#191919;border-color:#141414}#ComboViewerPanel Toolbar{border-bottom:1 solid #161616}#ComboViewerPanel Toolbar::separator:horizontal{margin:0 0 0 2}#ComboViewerPanel Toolbar QToolButton{margin:2 0 3 2}#ComboViewerToolOptions{border-bottom:1 solid #161616}#ComboViewer #ToolBarContainer,#ViewerPanel #ToolBarContainer,FlipBook #ToolBarContainer{background-color:transparent;border-top:2 solid #161616;border-bottom:1 solid #161616;padding-right:-1}#flipCustomize{margin-left:3}#flipCustomize::menu-button{background-color:transparent;width:35}#flipCustomize::menu-arrow{image:none}QToolBar#FlipConsolePlayToolBar::separator:horizontal{margin:0 3}QToolBar#FlipConsolePlayToolBar QToolButton{margin-top:2;margin-bottom:2;height:16;padding-left:1;padding-right:1}#ViewerFpsSlider{background-color:transparent;background-image:url('../Default/imgs/white/slider-groove_dark.svg');background-position:center center;background-repeat:repeat-x;border:0;height:19;margin:0 3 0 37;max-width:300;min-width:0}#ViewerFpsSlider::sub-line:horizontal{subcontrol-origin:absolute;background-color:#515151;border:1 solid #303030;border-top-left-radius:2;border-bottom-left-radius:2;height:16;left:-33;width:14}#ViewerFpsSlider::add-line:horizontal{subcontrol-position:left;background-color:#515151;border:1 solid #303030;border-top-right-radius:2;border-bottom-right-radius:2;left:18;height:16;image-position:center center;width:13}#ViewerFpsSlider::handle::horizontal{background-color:#898989;border:1 solid #898989;border-radius:2;margin:2 0 3 0;min-width:9;width:9;max-width:9}FlipSlider{qproperty-PBHeight:15;qproperty-PBOverlay:url('../Default/imgs/white/flipslider_dark.svg');qproperty-PBColorMarginLeft:1;qproperty-PBColorMarginTop:2;qproperty-PBColorMarginRight:1;qproperty-PBColorMarginBottom:2;qproperty-PBMarker:url('../Default/imgs/white/flipmarker_dark.svg');qproperty-PBMarkerMarginLeft:3;qproperty-PBMarkerMarginRight:3;qproperty-notStartedColor:rgba(205,101,101,0.78);qproperty-startedColor:#1abc3f;qproperty-baseColor:#1c1c1c;qproperty-finishedColor:#1c1c1c}Ruler{qproperty-ParentBGColor:#303030;qproperty-ScaleColor:#cecece}#RulerToolOptionValues{color:#000}#xsheetArea,#ScrollArea{background-color:#1c1c1c;border:0}#xsheetScrollArea{border:0}#cornerWidget QToolButton{padding:0}#xsheetColumnAreaMenu_Preview{background-color:#E6E678}#xsheetColumnAreaMenu_Lock{background-color:#F5F5F5}#xsheetColumnAreaMenu_Camstand{background-color:#FFA480}#xsheetColumnAreaMenu_Preview,#xsheetColumnAreaMenu_Lock,#xsheetColumnAreaMenu_Camstand{color:#000}#noteTextEdit{color:#000}XsheetViewer{qproperty-TextColor:#cecece;qproperty-BGColor:#282828;qproperty-LightLineColor:#1f1f1f;qproperty-MarkerLineColor:#1E96C4;qproperty-VerticalLineColor:#090909;qproperty-VerticalLineHeadColor:#686868;qproperty-PreviewFrameTextColor:#9fdaff;qproperty-CurrentRowBgColor:#506082;qproperty-OnionSkinAreaBgColor:#1e1e1e;qproperty-EmptyColumnHeadColor:#444;qproperty-SelectedColumnTextColor:#E66464;qproperty-EmptyCellColor:#303030;qproperty-NotEmptyColumnColor:#383838;qproperty-SelectedEmptyCellColor:#545454;qproperty-LevelColumnColor:#4C6E4C;qproperty-LevelColumnBorderColor:#8FB38F;qproperty-SelectedLevelColumnColor:#678667;qproperty-VectorColumnColor:#7B7B4C;qproperty-VectorColumnBorderColor:#BBBB9A;qproperty-SelectedVectorColumnColor:#949466;qproperty-ChildColumnColor:#6A526B;qproperty-ChildColumnBorderColor:#B1A3B3;qproperty-SelectedChildColumnColor:#816e82;qproperty-FullcolorColumnColor:#657A96;qproperty-FullcolorColumnBorderColor:#9EB8BB;qproperty-SelectedFullcolorColumnColor:#8895a6;qproperty-FxColumnColor:#56553C;qproperty-FxColumnBorderColor:#95958A;qproperty-SelectedFxColumnColor:#6f6e56;qproperty-ReferenceColumnColor:#616161;qproperty-ReferenceColumnBorderColor:#A2A2A2;qproperty-SelectedReferenceColumnColor:#7a7a7a;qproperty-PaletteColumnColor:#3A655F;qproperty-PaletteColumnBorderColor:#86ACA7;qproperty-SelectedPaletteColumnColor:#52807a;qproperty-MeshColumnColor:#684D86;qproperty-MeshColumnBorderColor:#BA92EF;qproperty-SelectedMeshColumnColor:#82689e;qproperty-SoundTextColumnColor:#c8c8c8;qproperty-SoundTextColumnBorderColor:#8c8c8c;qproperty-SelectedSoundTextColumnColor:#e2e2e2;qproperty-SoundColumnColor:#657456;qproperty-SoundColumnBorderColor:#A0AF7D;qproperty-SelectedSoundColumnColor:#7e8b72;qproperty-SoundColumnHlColor:#34FE5E;qproperty-SoundColumnTrackColor:#B6C29D;qproperty-ColumnHeadPastelizer:#000;qproperty-SelectedColumnHead:#506082;qproperty-LightLightBGColor:#303030;qproperty-LightBGColor:#d8d8d8;qproperty-DarkBGColor:#c9c9c9;qproperty-DarkLineColor:#7e7e7e;qproperty-XsheetColumnNameBgColor:rgba(0,0,0,0);qproperty-XsheetDragBarHighlightColor:rgba(255,255,255,0.5);qproperty-XsheetPreviewButtonBgOnColor:#c8c864;qproperty-XsheetPreviewButtonOnImage:url('../Default/imgs/white/x_prev_eye_on.svg');qproperty-XsheetPreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetPreviewButtonOffImage:url('../Default/imgs/white/x_prev_eye_off.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');qproperty-XsheetCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetCamstandButtonOffImage:url('../Default/imgs/white/x_table_view_off.svg');qproperty-XsheetLockButtonBgOnColor:rgba(255,255,255,0.3);qproperty-XsheetLockButtonOnImage:url('../Default/imgs/white/x_lock_on.svg');qproperty-XsheetLockButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetLockButtonOffImage:url('../Default/imgs/white/x_lock_off.svg');qproperty-XsheetConfigButtonBgColor:rgba(255,255,255,0);qproperty-XsheetConfigButtonImage:url('../Default/imgs/white/x_config.svg');qproperty-TimelinePreviewButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelinePreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineCamstandButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelineCamstandButtonTranspImage:url('../Default/imgs/white/timeline_toggle_transp.svg');qproperty-TimelineCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineLockButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOnImage:url('../Default/imgs/white/timeline_toggle_on.svg');qproperty-TimelineLockButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOffImage:url('../Default/imgs/white/timeline_toggle_off.svg');qproperty-TimelineConfigButtonBgColor:rgba(255,255,255,0);qproperty-TimelineConfigButtonImage:url('../Default/imgs/white/timeline_config.svg');qproperty-LayerHeaderPreviewImage:url('../Default/imgs/white/layer_header_prev_eye.svg');qproperty-LayerHeaderPreviewOverImage:url('../Default/imgs/white/layer_header_prev_eye_over.svg');qproperty-LayerHeaderCamstandImage:url('../Default/imgs/white/layer_header_table_view.svg');qproperty-LayerHeaderCamstandOverImage:url('../Default/imgs/white/layer_header_table_view_over.svg');qproperty-LayerHeaderLockImage:url('../Default/imgs/white/lock_on.svg');qproperty-LayerHeaderLockOverImage:url('../Default/imgs/white/lock_on_over.svg')}#XSheetToolbar{margin:0;padding:0;border:0}#XSheetToolbar QToolButton{padding:0;margin:4 1;min-height:19;height:19}#XSheetToolbar::separator:horizontal{margin:0 4}#FunctionEditor QToolBar{border-bottom:1 solid #161616}#FunctionEditor QToolBar QToolBar{border:0}#FunctionEditor QToolBar QLabel{margin-left:5}#FunctionEditor QToolBar QToolButton{height:18}#FunctionEditorTree{border-top:1 solid #161616}FunctionTreeView{qproperty-TextColor:#cecece;qproperty-CurrentTextColor:#E66464}FunctionPanel{qproperty-BGColor:#232323;qproperty-ValueLineColor:#161616;qproperty-FrameLineColor:#161616;qproperty-OtherCurvesColor:#707070;qproperty-RulerBackground:#1b1b1b;qproperty-TextColor:#cecece;qproperty-SubColor:#000;qproperty-SelectedColor:#FFA500}SpreadsheetViewer{qproperty-LightLightBGColor:#303030;qproperty-CurrentRowBgColor:#506082;qproperty-LightLineColor:#1f1f1f;qproperty-MarkerLineColor:#1E96C4;qproperty-BGColor:#383838;qproperty-VerticalLineColor:#090909;qproperty-KeyFrameColor:#995d1d;qproperty-KeyFrameBorderColor:#c9b04b;qproperty-SelectedKeyFrameColor:#be772b;qproperty-InBetweenColor:#666250;qproperty-InBetweenBorderColor:#cdcec8;qproperty-SelectedInBetweenColor:#7d7a6c;qproperty-SelectedEmptyColor:#545454;qproperty-SelectedSceneRangeEmptyColor:#5d5d5d;qproperty-TextColor:#cecece;qproperty-ColumnHeaderBorderColor:#686868;qproperty-SelectedColumnTextColor:#E66464}#ExpressionField{background-color:#cecece;border:1 solid #1b1b1b;margin:0}#FunctionSegmentViewerLinkButton{background-image:url('../Default/imgs/white/segment_unlinked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:hover{background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:checked{background-image:url('../Default/imgs/white/segment_linked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:disabled{background-image:url('../Default/imgs/white/segment_disabled.svg');background-repeat:no-repeat} \ No newline at end of file diff --git a/stuff/config/qss/Default/Default.qss b/stuff/config/qss/Default/Default.qss index 6373d80..cd9883e 100644 --- a/stuff/config/qss/Default/Default.qss +++ b/stuff/config/qss/Default/Default.qss @@ -1 +1 @@ -.button-show,#LoadLevelShowButton,#CleanupSettingsShowButton,#OutputSettingsShowButton,#FxSettingsPreviewShowButton{image:url('imgs/white/plus.svg');image-position:center center;margin:0;padding:1;min-width:10;min-height:10}.button-show:checked,#LoadLevelShowButton:checked,#CleanupSettingsShowButton:checked,#OutputSettingsShowButton:checked,#FxSettingsPreviewShowButton:checked{background-color:#313131;border-color:#2c2c2c;image:url('imgs/white/minus.svg')}.button-show:checked:pressed,#LoadLevelShowButton:checked:pressed,#CleanupSettingsShowButton:checked:pressed,#OutputSettingsShowButton:checked:pressed,#FxSettingsPreviewShowButton:checked:pressed{background-color:#313131;border-color:#2c2c2c}.button-show:checked:hover,#LoadLevelShowButton:checked:hover,#CleanupSettingsShowButton:checked:hover,#OutputSettingsShowButton:checked:hover,#FxSettingsPreviewShowButton:checked:hover{background-color:#363636}.button-tool,QToolButton,#CameraSettingsRadioButton::indicator,#ForceSquaredPixelButton,#SchematicBottomFrame QToolBar QToolButton,#EditToolLockButton::indicator,#flipCustomize{background-color:rgba(255,255,255,0);border:1 solid rgba(255,255,255,0);border-radius:2;color:#f3f3f3;margin:1;padding:0}.button-tool:hover,QToolButton:hover,#CameraSettingsRadioButton::indicator:hover,#ForceSquaredPixelButton:hover,#colorSliderAddButton:hover,#colorSliderSubButton:hover,#SchematicBottomFrame QToolBar QToolButton:hover,#EditToolLockButton::indicator:hover,#flipCustomize:hover{background-color:#767676;border-color:#767676;color:#f3f3f3}.button-tool:pressed,QToolButton:pressed,#CameraSettingsRadioButton::indicator:pressed,#ForceSquaredPixelButton:pressed,#colorSliderAddButton:pressed,#colorSliderSubButton:pressed,#SchematicBottomFrame QToolBar QToolButton:pressed,#EditToolLockButton::indicator:pressed,#flipCustomize:pressed{background-color:#313131;border-color:#2c2c2c;color:#f3f3f3}.button-tool:checked,QToolButton:checked,#CameraSettingsRadioButton::indicator:checked,#ForceSquaredPixelButton:checked,#SchematicBottomFrame QToolBar QToolButton:checked,#EditToolLockButton::indicator:checked,#flipCustomize:checked{background-color:#5385a6;border-color:#5385a6;color:#fff}.button-tool:checked:hover,QToolButton:checked:hover,#CameraSettingsRadioButton::indicator:checked:hover,#ForceSquaredPixelButton:checked:hover,#SchematicBottomFrame QToolBar QToolButton:checked:hover,#EditToolLockButton::indicator:checked:hover,#flipCustomize:checked:hover{background-color:#6c98b6;border-color:#6c98b6}.button-tool:disabled,QToolButton:disabled,#CameraSettingsRadioButton::indicator:disabled,#ForceSquaredPixelButton:disabled,#SchematicBottomFrame QToolBar QToolButton:disabled,#EditToolLockButton::indicator:disabled,#flipCustomize:disabled{color:#808080}.button-flat,PaletteViewer QToolBar QToolButton{background-color:none;border:0;border-radius:0;margin:0}.button-flat:hover,PaletteViewer QToolBar QToolButton:hover{background-color:#767676}.button-flat:pressed,PaletteViewer QToolBar QToolButton:pressed{background-color:#272727}.frame,.GroupBox,#LoadLevelFrame,#PsdSettingsGroupBox,#CleanupSettingsFrame,#OutputSettingsBox,#OutputSettingsCameraBox,#SolidLineFrame,#FunctionParametersPanel,QGroupBox{border:1 solid #272727;border-radius:2}.tab-container,#TabBarContainer{background-color:transparent;qproperty-BottomAboveLineColor:#393939;qproperty-BottomBelowLineColor:#272727}.tab-flat,#StyleEditorTabBar::tab,#PaletteTabBar::tab,#FxSettingsTabBar::tab{background-color:#393939;border-right:1 solid #272727;border-bottom:1 solid #272727;color:#a1a1a1;padding:3 4 3 4}.tab-flat:hover,#StyleEditorTabBar::tab:hover,#PaletteTabBar::tab:hover,#FxSettingsTabBar::tab:hover{background-color:#484848;color:#a1a1a1}.tab-flat:selected,#StyleEditorTabBar::tab:selected,#PaletteTabBar::tab:selected,#FxSettingsTabBar::tab:selected{background-color:#484848;color:#fff;border-bottom-color:#484848}.tab-flat:only-one,#StyleEditorTabBar::tab:only-one,#PaletteTabBar::tab:only-one,#FxSettingsTabBar::tab:only-one{margin:0}.tab-round{background-color:#393939;border-top:1 solid #272727;border-right:1 solid #272727;border-left:1 solid #272727;border-bottom:1 solid #272727;color:#a1a1a1;margin:3 -1 0 0;padding:2 7 1 7}.tab-round:hover{background-color:#484848;color:#a1a1a1}.tab-round:selected{background-color:#484848;border-top-right-radius:2;border-top-left-radius:2;border-bottom-color:#484848;color:#fff;margin:1 -1 -1 0;padding:2 7 2 7}.tab-round:only-one{margin:1 0 0 0;padding:3 7 3 7}.tab-round:last{margin-right:0;border-top-right-radius:2}.tab-round:first{border-top-left-radius:2}QWidget{background-color:#484848;color:#e6e6e6}QWidget:disabled{color:#808080}QFrame{border:0;margin:0;padding:0}QToolTip,#helpToolTip{background-color:#fff;border:1 solid #000;color:#000;padding:1 1}#DockSeparator,QMainWindow::separator,QSplitter::handle{background-color:#1a1a1a;height:4;width:4}#TDockPlaceholder{background-color:#F77272}TPanel{background-color:#1a1a1a}#TopBar{background:#484848;border:0;border-bottom:1 solid #272727;height:21}#TopBar #EditToolLockButton{background:#484848;spacing:0}#TopBar #EditToolLockButton::indicator{background:none;border:none;height:18;margin:1 2 0 0;padding-left:0;padding-right:0}#TopBarTabContainer{background-color:#484848;margin-bottom:1}#StackedMenuBar{border:0;margin:0;padding:0}QMenuBar{background-color:#484848;border:0}QMenuBar::item{background-color:#484848;border-left:1 solid #484848;margin:0;padding:3 5}QMenuBar::item:selected{background-color:rgba(255,255,255,0.15);color:#e6e6e6}QMenuBar::item:pressed{background-color:#5385a6;color:#fff}#TopBarTab{margin:0;padding:0}#TopBarTab::tab{background-color:#393939;border-top:1 solid #272727;border-right:1 solid #272727;color:#a1a1a1;margin:0 0 0 0;padding:2 8 3 8}#TopBarTab::tab:hover{background-color:#484848;color:#a1a1a1}#TopBarTab::tab:selected{background-color:#484848;color:#fff}#TopBarTab::tab:first{border-left:1 solid #272727}#TopBarTab::tab:last{border-right:1 solid #272727}QMenu{background-color:#484848;border:1 solid #272727;padding:2 0}QMenu::item{padding:3 28}QMenu::item:selected{background-color:#5385a6;color:#fff}QMenu::item:checked{color:#e6e6e6}QMenu::item:checked:selected{background-color:#5385a6;color:#fff}QMenu::item:disabled{background:none;color:#808080}QMenu::item:disabled:selected{border-color:transparent}QMenu::separator{border-top:1 solid #272727;height:0;margin:2 0}QMenu::icon{border-radius:2;margin:0 0 0 3;padding:1}QMenu::icon:checked{background-color:#5385a6}QMenu::indicator{margin-left:7}TPanelTitleBar{background-color:#393939;border-color:#272727;border-style:solid;border-width:0 0 1 0;height:20;min-height:20;qproperty-TitleColor:#949494;qproperty-ActiveTitleColor:#fff;qproperty-BorderPixmap:url('none');qproperty-ActiveBorderPixmap:url('imgs/white/none');qproperty-FloatBorderPixmap:url('none');qproperty-FloatActiveBorderPixmap:url('imgs/white/none')}QAbstractScrollArea::corner{background-color:#343434}QScrollBar{background-color:#343434;border:0}QScrollBar:horizontal{height:16;margin:0}QScrollBar:vertical{margin:0;width:16}QScrollBar::handle{border:1 solid #525252;border-radius:4}QScrollBar::handle:horizontal:hover,QScrollBar::handle:vertical:hover{background-color:#676767;border-color:#676767}QScrollBar::handle:horizontal:pressed,QScrollBar::handle:vertical:pressed{background-color:#7b7b7b;border-color:#7b7b7b}QScrollBar::handle:horizontal{background-color:#525252;margin:3 16;min-width:20}QScrollBar::handle:vertical{background-color:#525252;margin:16 3;min-height:20}QScrollBar::add-line{subcontrol-origin:margin;border:0}QScrollBar::add-line:horizontal{subcontrol-position:right;background-color:#343434;margin:0;width:16}QScrollBar::add-line:vertical{subcontrol-position:bottom;background-color:#343434;margin:0;height:16}QScrollBar::sub-line{border:0;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{subcontrol-position:left;background-color:#343434;margin:0;width:16}QScrollBar::sub-line:vertical{subcontrol-position:top;background-color:#343434;margin:0;height:16}QScrollBar::up-arrow:vertical{image:url('imgs/white/scroll-up.svg');image-position:center center}QScrollBar::up-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::down-arrow:vertical{image:url('imgs/white/scroll-down.svg');image-position:center center}QScrollBar::down-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::left-arrow:horizontal{image:url('imgs/white/scroll-left.svg');image-position:center center}QScrollBar::left-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::right-arrow:horizontal{image:url('imgs/white/scroll-right.svg');image-position:center center}QScrollBar::right-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::sub-page:horizontal,QScrollBar::add-page:horizontal,QScrollBar::sub-page:vertical,QScrollBar::add-page:vertical{background:none}QToolBar{padding:0}QToolBar::separator:horizontal{border-left:1 solid #272727;margin:0 1;width:0}QToolBar::separator:vertical{border-top:1 solid #272727;height:0;margin:1 0}QToolBar QLabel{margin-top:1}QToolBar QToolBar{border:0}QToolButton::menu-indicator{image:none}QToolButton::menu-button{border-image:none}.DvScrollWidget QPushButton,DvScrollWidget QPushButton,#ScrollLeftButton QPushButton,#ScrollRightButton QPushButton,#ScrollUpButton QPushButton,#ScrollDownButton QPushButton{background-color:#696969;border:0 solid red;border-radius:0;padding:0;max-width:16}.DvScrollWidget QPushButton:hover,DvScrollWidget QPushButton:hover,#ScrollLeftButton QPushButton:hover,#ScrollRightButton QPushButton:hover,#ScrollUpButton QPushButton:hover,#ScrollDownButton QPushButton:hover{background-color:#767676}.DvScrollWidget QPushButton:pressed,DvScrollWidget QPushButton:pressed,#ScrollLeftButton QPushButton:pressed,#ScrollRightButton QPushButton:pressed,#ScrollUpButton QPushButton:pressed,#ScrollDownButton QPushButton:pressed{background-color:#313131}#ScrollLeftButton,#ScrollRightButton,#ScrollUpButton,#ScrollDownButton{margin:0;min-width:16}#ScrollLeftButton{border-right:1 solid #272727;image:url('imgs/white/scroll-left.svg')}#ScrollRightButton{border-left:1 solid #272727;margin-left:3;image:url('imgs/white/scroll-right.svg')}#ScrollUpButton{image:url('imgs/white/scroll-up.svg')}#ScrollDownButton{image:url('imgs/white/scroll-down.svg')}#keyFrameNavigator{background:none;margin:0;padding:0}#keyFrameNavigator QToolButton{min-width:18}#keyFrameNavigator #PreviousKey{image:url('imgs/white/prevkey.svg')}#keyFrameNavigator #PreviousKey:hover{image:url('imgs/white/prevkey_over.svg')}#keyFrameNavigator #PreviousKey:disabled{image:url('imgs/white/prevkey_disabled.svg')}#keyFrameNavigator #NextKey{image:url('imgs/white/nextkey.svg')}#keyFrameNavigator #NextKey:hover{image:url('imgs/white/nextkey_over.svg')}#keyFrameNavigator #NextKey:disabled{image:url('imgs/white/nextkey_disabled.svg')}.treeview,QTreeWidget,QTreeView,#FunctionEditorTree{background-color:#343434;alternate-background-color:#393939;border:0;margin:0;outline:0}.treeview::item:selected,QTreeWidget::item:selected,QTreeView::item:selected,#FunctionEditorTree::item:selected{background-color:#5385a6;color:#fff}.treeview::branch:adjoins-item,QTreeWidget::branch:adjoins-item,QTreeView::branch:adjoins-item,#FunctionEditorTree::branch:adjoins-item{border-image:url('')}.treeview::branch:has-siblings,QTreeWidget::branch:has-siblings,QTreeView::branch:has-siblings,#FunctionEditorTree::branch:has-siblings{border-image:url('')}.treeview::branch:has-siblings:adjoins-item,QTreeWidget::branch:has-siblings:adjoins-item,QTreeView::branch:has-siblings:adjoins-item,#FunctionEditorTree::branch:has-siblings:adjoins-item{border-image:url('')}.treeview::branch:has-children:closed,QTreeWidget::branch:has-children:closed,QTreeView::branch:has-children:closed,#FunctionEditorTree::branch:has-children:closed{background:url('imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:open,QTreeWidget::branch:has-children:open,QTreeView::branch:has-children:open,#FunctionEditorTree::branch:has-children:open{background:url('imgs/white/treebranch-open.svg') no-repeat;background-position:center center;image:none}.treeview::branch:has-children:has-siblings:closed,QTreeWidget::branch:has-children:has-siblings:closed,QTreeView::branch:has-children:has-siblings:closed,#FunctionEditorTree::branch:has-children:has-siblings:closed{background:url('imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:has-siblings:open,QTreeWidget::branch:has-children:has-siblings:open,QTreeView::branch:has-children:has-siblings:open,#FunctionEditorTree::branch:has-children:has-siblings:open{background:url('imgs/white/treebranch-open.svg') no-repeat;background-position:center center;border-image:none;image:none}QListView{outline:0;background:#343434;alternate-background-color:#393939}#TabBarContainer{background-color:#393939}.Button,QPushButton,.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{background-color:#696969;border:1 solid #484848;border-radius:2;color:#f3f3f3;margin:0;padding:3 15}.Button:hover,QPushButton:hover,.ComboBox:hover,#ViewerFpsSlider::sub-line:horizontal:hover,#ViewerFpsSlider::add-line:horizontal:hover,QComboBox:hover{background-color:#767676;border-color:#484848;color:#f3f3f3}.Button:pressed,QPushButton:pressed,#ViewerFpsSlider::sub-line:horizontal:pressed,#ViewerFpsSlider::add-line:horizontal:pressed{background-color:#313131;border-color:#2c2c2c;color:#f3f3f3}.Button:checked,QPushButton:checked{background-color:#313131;border-color:#2c2c2c;color:#f3f3f3}.Button:checked:hover,QPushButton:checked:hover{background-color:#363636}.Button:checked:hover:pressed,QPushButton:checked:hover:pressed{background:#313131}.Button:disabled,QPushButton:disabled,.ComboBox:disabled,#ViewerFpsSlider::sub-line:horizontal:disabled,#ViewerFpsSlider::add-line:horizontal:disabled,QComboBox:disabled{background-color:#555;border-color:#484848;color:#808080}#PushButton_NoPadding{padding:3}.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{padding:1 0 1 4;margin:1 0}.ComboBox::drop-down,QComboBox::drop-down{image:url('imgs/white/combo_downarrow.svg');image-position:center center;width:16}.ComboBox::drop-down:disabled,QComboBox::drop-down:disabled{image:url('imgs/white/combo_downarrow_disabled.svg')}.ComboBox QAbstractItemView,QComboBox QAbstractItemView{background-color:#484848;border:1 solid #272727;selection-background-color:#5385a6;selection-color:#fff}.LineEdit,QLineEdit,#TaskSheetItem,#tasksRemoveBox,#tasksAddBox{background-color:#2f2f2f;border:1 solid #2c2c2c;border-radius:2;color:#e6e6e6;selection-background-color:#5385a6;selection-color:#fff;padding:0 0 0 1}.LineEdit:focus,QLineEdit:focus,#TaskSheetItem:focus,#tasksRemoveBox:focus,#tasksAddBox:focus{background-color:#2f2f2f;border-color:#5385a6;color:#e6e6e6}.LineEdit:disabled,QLineEdit:disabled,#TaskSheetItem:disabled,#tasksRemoveBox:disabled,#tasksAddBox:disabled{background-color:#3b3b3b;border-color:#3a3a3a;color:#808080}.CheckBox,QCheckBox{color:#e6e6e6}.CheckBox:hover,QCheckBox:hover,.RadioButton:hover,QRadioButton:hover{color:#fff}.CheckBox:disabled,QCheckBox:disabled{color:#808080}.CheckBox::indicator,QMenu::indicator,QCheckBox::indicator,.GroupBox::indicator,QGroupBox::indicator{background-color:#2f2f2f;border:1 solid #2c2c2c;border-radius:2;height:9;padding:1;width:9}.CheckBox::indicator:hover,QMenu::indicator:hover,.CheckBox::indicator:checked:hover,QCheckBox::indicator:hover,.GroupBox::indicator:hover,QMenu::indicator:checked:hover,QCheckBox::indicator:checked:hover,.GroupBox::indicator:checked:hover,QGroupBox::indicator:hover,QGroupBox::indicator:checked:hover{background-color:#2f2f2f;border-color:#5385a6}.CheckBox::indicator:checked,QMenu::indicator:checked,QCheckBox::indicator:checked,.GroupBox::indicator:checked,QGroupBox::indicator:checked{background-color:#2f2f2f;border-color:#2c2c2c;image:url('imgs/white/checkmark.svg')}.CheckBox::indicator:checked:disabled,QMenu::indicator:checked:disabled,QCheckBox::indicator:checked:disabled,.GroupBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled{background-color:#3b3b3b;border-color:#3b3b3b;image:url('imgs/white/checkmark_disabled.svg')}.CheckBox::indicator:disabled,QMenu::indicator:disabled,QCheckBox::indicator:disabled,.GroupBox::indicator:disabled,QGroupBox::indicator:disabled{background-color:#3b3b3b;border-color:#3b3b3b}.RadioButton::indicator:unchecked,QRadioButton::indicator:unchecked,#CameraSettingsRadioButton_Small::indicator:unchecked{image:url('imgs/white/radiobutton_unchecked.svg');image-position:center center}.RadioButton::indicator:checked,QRadioButton::indicator:checked,#CameraSettingsRadioButton_Small::indicator:checked{image:url('imgs/white/radiobutton_checked.svg');image-position:center center}.GroupBox,QGroupBox{margin:6 0 0 0;padding:5 0}.GroupBox::title,QGroupBox::title{subcontrol-origin:margin;left:15;margin:-3 0 0 0;padding:0 3}.GroupBox::title:hover,QGroupBox::title:hover{color:#fff}.GroupBox::title:disabled,QGroupBox::title:disabled{color:#808080}.GroupBox::indicator,QGroupBox::indicator{subcontrol-origin:margin;margin-top:2}.GroupBox:disabled,QGroupBox:disabled{color:#808080}.Slider::groove:horizontal,QSlider::groove:horizontal{background-color:transparent;background-image:url('imgs/white/slider-groove.svg');background-position:center center;background-repeat:repeat-x;margin:0;height:20;min-height:20}.Slider::groove:horizontal:disabled,QSlider::groove:horizontal:disabled{background-image:url('imgs/white/slider-groove_disabled.svg')}.Slider::handle:horizontal,QSlider::handle:horizontal{width:10;margin:-2 -1;image:url('imgs/white/slider-handle.svg')}.Slider::handle:horizontal:disabled,QSlider::handle:horizontal:disabled{image:url('imgs/white/slider-handle_disabled.svg')}#IntPairField,#DoublePairField{qproperty-LightLineColor:#2c2c2c;qproperty-LightLineEdgeColor:#2c2c2c;qproperty-DarkLineColor:#2c2c2c;qproperty-MiddleLineColor:#2c2c2c;qproperty-HandleLeftPixmap:url("imgs/white/slider-handle.svg");qproperty-HandleRightPixmap:url("imgs/white/slider-handle.svg");qproperty-HandleLeftGrayPixmap:url("imgs/white/slider-handle_disabled.svg");qproperty-HandleRightGrayPixmap:url("imgs/white/slider-handle_disabled.svg")}#DirTreeView{background-color:#343434;alternate-background-color:#343434;border:1 solid #272727;border-right:0}DvItemViewerPanel{qproperty-TextColor:#e6e6e6;qproperty-AlternateBackground:#404040;qproperty-SelectedTextColor:#fff;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedItemBackground:#5385a6}#FileBrowser DvItemViewerPanel,#SceneCast DvItemViewerPanel{background-color:#484848}#FileBrowser #castFrame,#SceneCast #castFrame{border-top:1 solid #272727;border-right:1 solid #272727;border-bottom:1 solid #272727;margin:0}#FileBrowser QToolButton,#SceneCast QToolButton{padding:1}DvDirTreeView{qproperty-TextColor:#e6e6e6;qproperty-SelectedTextColor:#fff;qproperty-SelectedItemBackground:#5385a6;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedFolderTextColor:#fff;alternate-background-color:#393939;background-color:#343434;border:1 solid #272727}#FileDoesNotExistLabel{color:#f00}#SceneCast QToolBar{border-top:1 solid #272727}#SceneCast QToolButton{margin:3 1 2 1;padding:1}#CastBrowser{border:0;margin:0}#FilmStrip QComboBox{border-radius:0;border-width:0}#FilmStrip QComboBox QAbstractItemView{background-color:#484848}#CleanupSettings #CleanupSettingsFrame{margin-top:2;margin-bottom:4}#CleanupSettings QGroupBox{margin-bottom:3}ParamsPage{qproperty-TextColor:#e6e6e6}#CameraSettingsButton{padding:2}#CameraSettingsRadioButton:hover{background:none}#CameraSettingsRadioButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#CameraSettingsRadioButton::indicator:unchecked{image:url('imgs/white/lock_off.svg')}#CameraSettingsRadioButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('imgs/white/lock_on.svg')}#CameraSettingsRadioButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#CameraSettingsDPI{color:#9fdaff}#CameraSettingsRadioButton_Small{padding:0}#CameraSettingsRadioButton_Small::indicator{background-color:transparent;border:0;height:21;margin:0;width:11}#ForceSquaredPixelButton{height:16;border:1 solid rgba(255,255,255,0);image:url('imgs/white/fsp_unchecked.svg');padding:2;width:16;margin:0}#ForceSquaredPixelButton:checked{image:url('imgs/white/fsp_checked.svg')}#OutputSettingsLabel{color:#9fdaff}PencilTestPopup{min-height:730px;min-width:512px}#MatchLineButton{background-color:#6e6e6e}#MatchLineButton:checked{background-color:#949494;border:2 solid #5385a6;border-radius:2}#LargeSizedText{font-size:17}#StartupLabel{padding:3}#StartupLabel:hover{background:#626262}QStatusBar{background-color:#c0c0c0}QStatusBar::item{border:0}QStatusBar QLabel{background-color:#c0c0c0}QStatusBar #StatusBarLabel{background-color:#fff;padding:1 3}#TitleTxtLabel{color:#9fdaff}#StyleEditor QPushButton{margin:2 1;padding:0}#StyleEditor #TabBarContainer{margin-left:-4}#StyleEditor #bottomWidget{border-top:1 solid #272727;padding:3 2 8 3}#StyleEditor #bottomWidget QPushButton{padding:3 5}#StyleEditorTabBar::tab::first{border-left:1 solid #272727}#HexagonalColorWheel{qproperty-BGColor:#484848}#colorSlider::groove:horizontal{height:1;border-image:none}#colorSlider::handle:horizontal{width:8;margin:-8 -4}#colorSliderAddButton,#colorSliderSubButton{background:none;border-color:transparent;image-position:center center;min-height:16;padding:0;min-width:18}#colorSliderAddButton{image:url('imgs/white/scroll-right.svg')}#colorSliderSubButton{image:url('imgs/white/scroll-left.svg')}#PlainColorPageParts{border-bottom:1 solid #272727}#PlainColorPageParts QLineEdit{max-width:35}PaletteViewer DvScrollWidget QPushButton{border-top:0;margin-bottom:1;max-width:15;min-width:15}PaletteViewer DvScrollWidget #ScrollLeftButton{border-radius:0;margin-bottom:1;max-width:16;min-width:16}PaletteViewer DvScrollWidget #ScrollRightButton{border-radius:0;margin-left:1;margin-bottom:1;max-width:16;min-width:16}PaletteViewer QToolBar{background:none;border-bottom:1 solid #272727;padding:0;margin:0}PaletteViewer QToolBar::separator:horizontal{margin:0}PaletteViewer QToolBar QToolButton{margin:0 0 1 0;padding:1 0 2 0}#PageViewer{qproperty-TextColor:#e6e6e6}#PaletteLockButton{border-radius:0;margin:0 0 1 1}#PaletteLockButton:checked{background-color:#C34040;border-color:#C34040}#PaletteLockButton:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#WordButton{padding-right:0;padding-left:0}QDialog{background-color:#484848}QDialog #dialogButtonFrame{background-color:#3e3e3e;border-top:1 solid #272727}QDialog #dialogButtonFrame QPushButton{border-color:#3e3e3e;outline:0}QDialog #dialogButtonFrame QPushButton:focus{background-color:#5385a6;border-color:#3e3e3e;color:#fff}QDialog #dialogButtonFrame QPushButton:focus:hover{background-color:#6c98b6}QDialog #dialogButtonFrame QPushButton:focus:pressed{background-color:#313131;border-color:#2c2c2c;color:#f3f3f3}#SceneSettings QLabel{color:#9fdaff}#PreferencesPopup QListWidget{background-color:#343434;alternate-background-color:#343434;border:1 solid #272727;font-size:13}#PreferencesPopup QListWidget::item{border:0;padding:3}#PreferencesPopup QListWidget::item:hover{color:#e6e6e6;background-color:rgba(255,255,255,0.15)}#PreferencesPopup QListWidget::item:selected{background-color:#5385a6;color:#fff}#ShortcutTree{border:1 solid #272727}#ShortcutTree::item{padding:1 0}#ShortcutTree QScrollBar:vertical{width:16;margin-right:-1}ProjectPopup QLabel{color:#9fdaff}#GearButton{qproperty-icon:url('imgs/white/gear.svg')}#SubfolderButton{qproperty-icon:url('imgs/white/subfolder.svg')}SchematicViewer{qproperty-TextColor:#e6e6e6;qproperty-VerticalLineColor:#222;qproperty-LevelColumnColor:#4C6E4C;qproperty-VectorColumnColor:#7B7B4C;qproperty-ChildColumnColor:#6A526B;qproperty-FullcolorColumnColor:#657A96;qproperty-FxColumnColor:#56553C;qproperty-PaletteColumnColor:#3A655F;qproperty-MeshColumnColor:#684D86;qproperty-TableColor:#62628c;qproperty-ActiveCameraColor:#2d7dca;qproperty-OtherCameraColor:#6c797b;qproperty-GroupColor:#3b6e9c;qproperty-PegColor:#9f6e3c;qproperty-SplineColor:#6a9d1c;qproperty-ActiveOutputColor:#2d7dca;qproperty-OtherOutputColor:#6c797b;qproperty-XsheetColor:#62628c;qproperty-NormalFxColor:#6a7e96;qproperty-MacroFxColor:#815c79;qproperty-ImageAdjustFxColor:#656287;qproperty-LayerBlendingFxColor:#4f757d;qproperty-MatteFxColor:#ae7171;qproperty-SchematicPreviewButtonBgOnColor:#c8c864;qproperty-SchematicPreviewButtonOnImage:url('imgs/white/x_prev_eye_on.svg');qproperty-SchematicPreviewButtonBgOffColor:rgba(200,200,100,0.5);qproperty-SchematicPreviewButtonOffImage:url('imgs/white/x_prev_eye_off.svg');qproperty-SchematicCamstandButtonBgOnColor:#eb906b;qproperty-SchematicCamstandButtonOnImage:url('imgs/white/x_table_view_on.svg');qproperty-SchematicCamstandButtonTranspImage:url('imgs/white/x_table_view_transp.svg');qproperty-SchematicCamstandButtonBgOffColor:rgba(235,144,107,0.5);qproperty-SchematicCamstandButtonOffImage:url('imgs/white/x_table_view_off.svg')}#SchematicBottomFrame{background-color:#484848;border:0;margin:0;padding:0}#SchematicBottomFrame QToolBar::separator:horizontal{margin:0}#SchematicBottomFrame QToolBar QToolButton{padding:0;margin:2}#SchematicSceneViewer{background-color:#3b3b3b;border-bottom:1 solid #272727}#FxSettingsTabBar::tab{border-top:1 solid #272727}#FxSettingsTabBar::tab::first,#FxSettingsTabBar::tab::only-one{border-left:1 solid #272727}FxSettings QToolBar{border-top:1 solid #272727;border-right:1 solid #272727;border-left:1 solid #272727;min-height:23;padding:3 0}FxSettings QToolBar QToolBar{border:0}#FxSettingsLabel{color:#a0e680}#FxSettingsHelpButton{background-color:#80a0dc;color:#000;padding-top:0;padding-bottom:0}#FxSettingsHelpButton:hover{background-color:#a8bee7}#ScriptConsole{font-family:'Courier New',monospace;border:0;color:#000000;padding:3}#ScriptConsole QFrame{background-color:#dcdcdc}#ScriptConsole TPanelTitleBar{background-color:#393939}#TaskSheetItemLabel{color:#e6e6e6}#Tasks QToolBar{border-bottom:1 solid #272727;margin:0;padding:0}#Tasks QToolBar QToolButton{margin:2 2 3 2}#ToolBar QToolBar{padding-left:2}#ToolOptions TPanelTitleBar{border-right:1 solid #272727;border-bottom:0}#CommandBar TPanelTitleBar{border-right:1 solid #272727;border-bottom:0}IconViewField{qproperty-ThicknessPixmap:url("imgs/white/selectiontool_thickness.svg")}#EditToolLockButton{spacing:0}#EditToolLockButton:hover{background:none}#EditToolLockButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#EditToolLockButton::indicator:unchecked{image:url('imgs/white/lock_off.svg')}#EditToolLockButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('imgs/white/lock_on.svg')}#EditToolLockButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}PopupButton::menu-indicator{border-left:0;height:17;image:url('imgs/white/combo_downarrow.svg');width:10}PopupButton::menu-indicator:hover{image:url('imgs/white/combo_downarrow.svg')}PopupButton::menu-indicator:disabled{image:url('imgs/white/combo_downarrow_disabled.svg')}#Cap,#Join{padding:0 4 0 -8;max-width:32;min-width:32}#Cap QMenu,#Join QMenu{max-width:28;min-width:28}#Cap QMenu::item,#Join QMenu::item{max-width:28;min-width:28;padding:0}QToolBar#MediumPaddingToolBar QToolButton{padding-left:3;padding-right:3}QToolBar#WidePaddingToolBar QToolButton{padding-left:6;padding-right:6}#CommandBar{margin:0;padding:0;border:0}#CommandBar::separator:horizontal{margin-right:3;margin-left:3}#expandButton:checked{background-color:transparent;border-color:transparent;color:#e6e6e6}#expandButton:checked:hover{background-color:#767676;border-color:#767676}#expandButton:checked:pressed{background-color:#313131;border-color:#2c2c2c}#ComboViewerPanel Toolbar{border-bottom:1 solid #272727}#ComboViewerPanel Toolbar::separator:horizontal{margin:0 0 0 2}#ComboViewerPanel Toolbar QToolButton{margin:2 0 3 2}#ComboViewerToolOptions{border-bottom:1 solid #272727}#ComboViewer #ToolBarContainer,#ViewerPanel #ToolBarContainer,FlipBook #ToolBarContainer{background-color:transparent;border-top:2 solid #272727;border-bottom:1 solid #272727;padding-right:-1}#flipCustomize{margin-left:3}#flipCustomize::menu-button{background-color:transparent;width:35}#flipCustomize::menu-arrow{image:none}QToolBar#FlipConsolePlayToolBar::separator:horizontal{margin:0 3}QToolBar#FlipConsolePlayToolBar QToolButton{margin-top:2;margin-bottom:2;height:16;padding-left:1;padding-right:1}#ViewerFpsSlider{background-color:transparent;background-image:url('imgs/white/slider-groove.svg');background-position:center center;background-repeat:repeat-x;border:0;height:19;margin:0 3 0 37;max-width:300;min-width:0}#ViewerFpsSlider::sub-line:horizontal{subcontrol-origin:absolute;background-color:#696969;border:1 solid #484848;border-top-left-radius:2;border-bottom-left-radius:2;height:16;left:-33;width:14}#ViewerFpsSlider::add-line:horizontal{subcontrol-position:left;background-color:#696969;border:1 solid #484848;border-top-right-radius:2;border-bottom-right-radius:2;left:18;height:16;image-position:center center;width:13}#ViewerFpsSlider::handle::horizontal{background-color:#a1a1a1;border:1 solid #a1a1a1;border-radius:2;margin:2 0 3 0;min-width:9;width:9;max-width:9}FlipSlider{qproperty-PBHeight:15;qproperty-PBOverlay:url('imgs/white/flipslider.svg');qproperty-PBColorMarginLeft:1;qproperty-PBColorMarginTop:2;qproperty-PBColorMarginRight:1;qproperty-PBColorMarginBottom:2;qproperty-PBMarker:url('imgs/white/flipmarker.svg');qproperty-PBMarkerMarginLeft:3;qproperty-PBMarkerMarginRight:3;qproperty-notStartedColor:rgba(205,101,101,0.78);qproperty-startedColor:#1abc3f;qproperty-baseColor:#2f2f2f;qproperty-finishedColor:#2f2f2f}Ruler{qproperty-ParentBGColor:#484848;qproperty-ScaleColor:#e6e6e6}#RulerToolOptionValues{color:#000}#xsheetArea,#ScrollArea{background-color:#343434;border:0}#xsheetScrollArea{border:0}#cornerWidget QToolButton{padding:0}#xsheetColumnAreaMenu_Preview{background-color:#E6E678}#xsheetColumnAreaMenu_Lock{background-color:#F5F5F5}#xsheetColumnAreaMenu_Camstand{background-color:#FFA480}#xsheetColumnAreaMenu_Preview,#xsheetColumnAreaMenu_Lock,#xsheetColumnAreaMenu_Camstand{color:#000}#noteTextEdit{color:#000}XsheetViewer{qproperty-TextColor:#e6e6e6;qproperty-BGColor:#3b3b3b;qproperty-LightLineColor:#2c2c2c;qproperty-MarkerLineColor:#1E96C4;qproperty-VerticalLineColor:#222;qproperty-VerticalLineHeadColor:#808080;qproperty-PreviewFrameTextColor:#9fdaff;qproperty-CurrentRowBgColor:#506082;qproperty-EmptyColumnHeadColor:#626262;qproperty-SelectedColumnTextColor:#E66464;qproperty-EmptyCellColor:#404040;qproperty-NotEmptyColumnColor:#484848;qproperty-SelectedEmptyCellColor:#6c6c6c;qproperty-LevelColumnColor:#4C6E4C;qproperty-LevelColumnBorderColor:#8FB38F;qproperty-SelectedLevelColumnColor:#678667;qproperty-VectorColumnColor:#7B7B4C;qproperty-VectorColumnBorderColor:#BBBB9A;qproperty-SelectedVectorColumnColor:#949466;qproperty-ChildColumnColor:#6A526B;qproperty-ChildColumnBorderColor:#B1A3B3;qproperty-SelectedChildColumnColor:#816e82;qproperty-FullcolorColumnColor:#657A96;qproperty-FullcolorColumnBorderColor:#9EB8BB;qproperty-SelectedFullcolorColumnColor:#8895a6;qproperty-FxColumnColor:#56553C;qproperty-FxColumnBorderColor:#95958A;qproperty-SelectedFxColumnColor:#6f6e56;qproperty-ReferenceColumnColor:#616161;qproperty-ReferenceColumnBorderColor:#A2A2A2;qproperty-SelectedReferenceColumnColor:#7a7a7a;qproperty-PaletteColumnColor:#3A655F;qproperty-PaletteColumnBorderColor:#86ACA7;qproperty-SelectedPaletteColumnColor:#52807a;qproperty-MeshColumnColor:#684D86;qproperty-MeshColumnBorderColor:#BA92EF;qproperty-SelectedMeshColumnColor:#82689e;qproperty-SoundTextColumnColor:#c8c8c8;qproperty-SoundTextColumnBorderColor:#8c8c8c;qproperty-SelectedSoundTextColumnColor:#e2e2e2;qproperty-SoundColumnColor:#657456;qproperty-SoundColumnBorderColor:#A0AF7D;qproperty-SelectedSoundColumnColor:#7e8b72;qproperty-SoundColumnHlColor:#34FE5E;qproperty-SoundColumnTrackColor:#B6C29D;qproperty-ColumnHeadPastelizer:#000;qproperty-SelectedColumnHead:#506082;qproperty-LightLightBGColor:#404040;qproperty-LightBGColor:#f0f0f0;qproperty-DarkBGColor:#e1e1e1;qproperty-DarkLineColor:#969696;qproperty-XsheetColumnNameBgColor:rgba(0,0,0,0);qproperty-XsheetDragBarHighlightColor:rgba(255,255,255,0.5);qproperty-XsheetPreviewButtonBgOnColor:#c8c864;qproperty-XsheetPreviewButtonOnImage:url('imgs/white/x_prev_eye_on.svg');qproperty-XsheetPreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetPreviewButtonOffImage:url('imgs/white/x_prev_eye_off.svg');qproperty-XsheetCamstandButtonBgOnColor:#eb906b;qproperty-XsheetCamstandButtonOnImage:url('imgs/white/x_table_view_on.svg');qproperty-XsheetCamstandButtonTranspImage:url('imgs/white/x_table_view_transp.svg');qproperty-XsheetCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetCamstandButtonOffImage:url('imgs/white/x_table_view_off.svg');qproperty-XsheetLockButtonBgOnColor:rgba(255,255,255,0.3);qproperty-XsheetLockButtonOnImage:url('imgs/white/x_lock_on.svg');qproperty-XsheetLockButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetLockButtonOffImage:url('imgs/white/x_lock_off.svg');qproperty-XsheetConfigButtonBgColor:rgba(255,255,255,0);qproperty-XsheetConfigButtonImage:url('imgs/white/x_config.svg');qproperty-TimelinePreviewButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOnImage:url('imgs/white/timeline_toggle_on.svg');qproperty-TimelinePreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOffImage:url('imgs/white/timeline_toggle_off.svg');qproperty-TimelineCamstandButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOnImage:url('imgs/white/timeline_toggle_on.svg');qproperty-TimelineCamstandButtonTranspImage:url('imgs/white/timeline_toggle_transp.svg');qproperty-TimelineCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOffImage:url('imgs/white/timeline_toggle_off.svg');qproperty-TimelineLockButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOnImage:url('imgs/white/timeline_toggle_on.svg');qproperty-TimelineLockButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOffImage:url('imgs/white/timeline_toggle_off.svg');qproperty-TimelineConfigButtonBgColor:rgba(255,255,255,0);qproperty-TimelineConfigButtonImage:url('imgs/white/timeline_config.svg');qproperty-LayerHeaderPreviewImage:url('imgs/white/layer_header_prev_eye.svg');qproperty-LayerHeaderPreviewOverImage:url('imgs/white/layer_header_prev_eye_over.svg');qproperty-LayerHeaderCamstandImage:url('imgs/white/layer_header_table_view.svg');qproperty-LayerHeaderCamstandOverImage:url('imgs/white/layer_header_table_view_over.svg');qproperty-LayerHeaderLockImage:url('imgs/white/lock_on.svg');qproperty-LayerHeaderLockOverImage:url('imgs/white/lock_on_over.svg')}#XSheetToolbar{margin:0;padding:0;border:0}#XSheetToolbar QToolButton{padding:0;margin:4 1;min-height:19;height:19}#XSheetToolbar::separator:horizontal{margin:0 4}#FunctionEditor QToolBar{border-bottom:1 solid #272727}#FunctionEditor QToolBar QToolBar{border:0}#FunctionEditor QToolBar QLabel{margin-left:5}#FunctionEditor QToolBar QToolButton{height:18}#FunctionEditorTree{border-top:1 solid #272727}FunctionTreeView{qproperty-TextColor:#e6e6e6;qproperty-CurrentTextColor:#E66464}FunctionPanel{qproperty-BGColor:#3b3b3b;qproperty-ValueLineColor:#2f2f2f;qproperty-FrameLineColor:#2f2f2f;qproperty-OtherCurvesColor:#888;qproperty-RulerBackground:#333;qproperty-TextColor:#e6e6e6;qproperty-SubColor:#000;qproperty-SelectedColor:#FFA500}SpreadsheetViewer{qproperty-LightLightBGColor:#404040;qproperty-CurrentRowBgColor:#506082;qproperty-LightLineColor:#2c2c2c;qproperty-MarkerLineColor:#1E96C4;qproperty-BGColor:#484848;qproperty-VerticalLineColor:#222;qproperty-KeyFrameColor:#995d1d;qproperty-KeyFrameBorderColor:#c9b04b;qproperty-SelectedKeyFrameColor:#be772b;qproperty-InBetweenColor:#666250;qproperty-InBetweenBorderColor:#cdcec8;qproperty-SelectedInBetweenColor:#7d7a6c;qproperty-SelectedEmptyColor:#6c6c6c;qproperty-SelectedSceneRangeEmptyColor:#757575;qproperty-TextColor:#e6e6e6;qproperty-ColumnHeaderBorderColor:#808080;qproperty-SelectedColumnTextColor:#E66464}#ExpressionField{background-color:#e6e6e6;border:1 solid #333;margin:0}#FunctionSegmentViewerLinkButton{background-image:url('imgs/white/segment_unlinked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:hover{background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:checked{background-image:url('imgs/white/segment_linked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:disabled{background-image:url('imgs/white/segment_disabled.svg');background-repeat:no-repeat} \ No newline at end of file +.button-show,#LoadLevelShowButton,#CleanupSettingsShowButton,#OutputSettingsShowButton,#FxSettingsPreviewShowButton{image:url('imgs/white/plus.svg');image-position:center center;margin:0;padding:1;min-width:10;min-height:10}.button-show:checked,#LoadLevelShowButton:checked,#CleanupSettingsShowButton:checked,#OutputSettingsShowButton:checked,#FxSettingsPreviewShowButton:checked{background-color:#313131;border-color:#2c2c2c;image:url('imgs/white/minus.svg')}.button-show:checked:pressed,#LoadLevelShowButton:checked:pressed,#CleanupSettingsShowButton:checked:pressed,#OutputSettingsShowButton:checked:pressed,#FxSettingsPreviewShowButton:checked:pressed{background-color:#313131;border-color:#2c2c2c}.button-show:checked:hover,#LoadLevelShowButton:checked:hover,#CleanupSettingsShowButton:checked:hover,#OutputSettingsShowButton:checked:hover,#FxSettingsPreviewShowButton:checked:hover{background-color:#363636}.button-tool,QToolButton,#CameraSettingsRadioButton::indicator,#ForceSquaredPixelButton,#SchematicBottomFrame QToolBar QToolButton,#EditToolLockButton::indicator,#flipCustomize{background-color:rgba(255,255,255,0);border:1 solid rgba(255,255,255,0);border-radius:2;color:#f3f3f3;margin:1;padding:0}.button-tool:hover,QToolButton:hover,#CameraSettingsRadioButton::indicator:hover,#ForceSquaredPixelButton:hover,#colorSliderAddButton:hover,#colorSliderSubButton:hover,#SchematicBottomFrame QToolBar QToolButton:hover,#EditToolLockButton::indicator:hover,#flipCustomize:hover{background-color:#767676;border-color:#767676;color:#f3f3f3}.button-tool:pressed,QToolButton:pressed,#CameraSettingsRadioButton::indicator:pressed,#ForceSquaredPixelButton:pressed,#colorSliderAddButton:pressed,#colorSliderSubButton:pressed,#SchematicBottomFrame QToolBar QToolButton:pressed,#EditToolLockButton::indicator:pressed,#flipCustomize:pressed{background-color:#313131;border-color:#2c2c2c;color:#f3f3f3}.button-tool:checked,QToolButton:checked,#CameraSettingsRadioButton::indicator:checked,#ForceSquaredPixelButton:checked,#SchematicBottomFrame QToolBar QToolButton:checked,#EditToolLockButton::indicator:checked,#flipCustomize:checked{background-color:#5385a6;border-color:#5385a6;color:#fff}.button-tool:checked:hover,QToolButton:checked:hover,#CameraSettingsRadioButton::indicator:checked:hover,#ForceSquaredPixelButton:checked:hover,#SchematicBottomFrame QToolBar QToolButton:checked:hover,#EditToolLockButton::indicator:checked:hover,#flipCustomize:checked:hover{background-color:#6c98b6;border-color:#6c98b6}.button-tool:disabled,QToolButton:disabled,#CameraSettingsRadioButton::indicator:disabled,#ForceSquaredPixelButton:disabled,#SchematicBottomFrame QToolBar QToolButton:disabled,#EditToolLockButton::indicator:disabled,#flipCustomize:disabled{color:#808080}.button-flat,PaletteViewer QToolBar QToolButton{background-color:none;border:0;border-radius:0;margin:0}.button-flat:hover,PaletteViewer QToolBar QToolButton:hover{background-color:#767676}.button-flat:pressed,PaletteViewer QToolBar QToolButton:pressed{background-color:#272727}.frame,.GroupBox,#LoadLevelFrame,#PsdSettingsGroupBox,#CleanupSettingsFrame,#OutputSettingsBox,#OutputSettingsCameraBox,#SolidLineFrame,#FunctionParametersPanel,QGroupBox{border:1 solid #272727;border-radius:2}.tab-container,#TabBarContainer{background-color:transparent;qproperty-BottomAboveLineColor:#393939;qproperty-BottomBelowLineColor:#272727}.tab-flat,#StyleEditorTabBar::tab,#PaletteTabBar::tab,#FxSettingsTabBar::tab{background-color:#393939;border-right:1 solid #272727;border-bottom:1 solid #272727;color:#a1a1a1;padding:3 4 3 4}.tab-flat:hover,#StyleEditorTabBar::tab:hover,#PaletteTabBar::tab:hover,#FxSettingsTabBar::tab:hover{background-color:#484848;color:#a1a1a1}.tab-flat:selected,#StyleEditorTabBar::tab:selected,#PaletteTabBar::tab:selected,#FxSettingsTabBar::tab:selected{background-color:#484848;color:#fff;border-bottom-color:#484848}.tab-flat:only-one,#StyleEditorTabBar::tab:only-one,#PaletteTabBar::tab:only-one,#FxSettingsTabBar::tab:only-one{margin:0}.tab-round{background-color:#393939;border-top:1 solid #272727;border-right:1 solid #272727;border-left:1 solid #272727;border-bottom:1 solid #272727;color:#a1a1a1;margin:3 -1 0 0;padding:2 7 1 7}.tab-round:hover{background-color:#484848;color:#a1a1a1}.tab-round:selected{background-color:#484848;border-top-right-radius:2;border-top-left-radius:2;border-bottom-color:#484848;color:#fff;margin:1 -1 -1 0;padding:2 7 2 7}.tab-round:only-one{margin:1 0 0 0;padding:3 7 3 7}.tab-round:last{margin-right:0;border-top-right-radius:2}.tab-round:first{border-top-left-radius:2}QWidget{background-color:#484848;color:#e6e6e6}QWidget:disabled{color:#808080}QFrame{border:0;margin:0;padding:0}QToolTip,#helpToolTip{background-color:#fff;border:1 solid #000;color:#000;padding:1 1}#DockSeparator,QMainWindow::separator,QSplitter::handle{background-color:#1a1a1a;height:4;width:4}#TDockPlaceholder{background-color:#F77272}TPanel{background-color:#1a1a1a}#TopBar{background:#484848;border:0;border-bottom:1 solid #272727;height:21}#TopBar #EditToolLockButton{background:#484848;spacing:0}#TopBar #EditToolLockButton::indicator{background:none;border:none;height:18;margin:1 2 0 0;padding-left:0;padding-right:0}#TopBarTabContainer{background-color:#484848;margin-bottom:1}#StackedMenuBar{border:0;margin:0;padding:0}QMenuBar{background-color:#484848;border:0}QMenuBar::item{background-color:#484848;border-left:1 solid #484848;margin:0;padding:3 5}QMenuBar::item:selected{background-color:rgba(255,255,255,0.15);color:#e6e6e6}QMenuBar::item:pressed{background-color:#5385a6;color:#fff}#TopBarTab{margin:0;padding:0}#TopBarTab::tab{background-color:#393939;border-top:1 solid #272727;border-right:1 solid #272727;color:#a1a1a1;margin:0 0 0 0;padding:2 8 3 8}#TopBarTab::tab:hover{background-color:#484848;color:#a1a1a1}#TopBarTab::tab:selected{background-color:#484848;color:#fff}#TopBarTab::tab:first{border-left:1 solid #272727}#TopBarTab::tab:last{border-right:1 solid #272727}QMenu{background-color:#484848;border:1 solid #272727;padding:2 0}QMenu::item{padding:3 28}QMenu::item:selected{background-color:#5385a6;color:#fff}QMenu::item:checked{color:#e6e6e6}QMenu::item:checked:selected{background-color:#5385a6;color:#fff}QMenu::item:disabled{background:none;color:#808080}QMenu::item:disabled:selected{border-color:transparent}QMenu::separator{border-top:1 solid #272727;height:0;margin:2 0}QMenu::icon{border-radius:2;margin:0 0 0 3;padding:1}QMenu::icon:checked{background-color:#5385a6}QMenu::indicator{margin-left:7}TPanelTitleBar{background-color:#393939;border-color:#272727;border-style:solid;border-width:0 0 1 0;height:20;min-height:20;qproperty-TitleColor:#949494;qproperty-ActiveTitleColor:#fff;qproperty-BorderPixmap:url('none');qproperty-ActiveBorderPixmap:url('imgs/white/none');qproperty-FloatBorderPixmap:url('none');qproperty-FloatActiveBorderPixmap:url('imgs/white/none')}QAbstractScrollArea::corner{background-color:#343434}QScrollBar{background-color:#343434;border:0}QScrollBar:horizontal{height:16;margin:0}QScrollBar:vertical{margin:0;width:16}QScrollBar::handle{border:1 solid #525252;border-radius:4}QScrollBar::handle:horizontal:hover,QScrollBar::handle:vertical:hover{background-color:#676767;border-color:#676767}QScrollBar::handle:horizontal:pressed,QScrollBar::handle:vertical:pressed{background-color:#7b7b7b;border-color:#7b7b7b}QScrollBar::handle:horizontal{background-color:#525252;margin:3 16;min-width:20}QScrollBar::handle:vertical{background-color:#525252;margin:16 3;min-height:20}QScrollBar::add-line{subcontrol-origin:margin;border:0}QScrollBar::add-line:horizontal{subcontrol-position:right;background-color:#343434;margin:0;width:16}QScrollBar::add-line:vertical{subcontrol-position:bottom;background-color:#343434;margin:0;height:16}QScrollBar::sub-line{border:0;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{subcontrol-position:left;background-color:#343434;margin:0;width:16}QScrollBar::sub-line:vertical{subcontrol-position:top;background-color:#343434;margin:0;height:16}QScrollBar::up-arrow:vertical{image:url('imgs/white/scroll-up.svg');image-position:center center}QScrollBar::up-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::down-arrow:vertical{image:url('imgs/white/scroll-down.svg');image-position:center center}QScrollBar::down-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::left-arrow:horizontal{image:url('imgs/white/scroll-left.svg');image-position:center center}QScrollBar::left-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::right-arrow:horizontal{image:url('imgs/white/scroll-right.svg');image-position:center center}QScrollBar::right-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::sub-page:horizontal,QScrollBar::add-page:horizontal,QScrollBar::sub-page:vertical,QScrollBar::add-page:vertical{background:none}QToolBar{padding:0}QToolBar::separator:horizontal{border-left:1 solid #272727;margin:0 1;width:0}QToolBar::separator:vertical{border-top:1 solid #272727;height:0;margin:1 0}QToolBar QLabel{margin-top:1}QToolBar QToolBar{border:0}QToolButton::menu-indicator{image:none}QToolButton::menu-button{border-image:none}.DvScrollWidget QPushButton,DvScrollWidget QPushButton,#ScrollLeftButton QPushButton,#ScrollRightButton QPushButton,#ScrollUpButton QPushButton,#ScrollDownButton QPushButton{background-color:#696969;border:0 solid red;border-radius:0;padding:0;max-width:16}.DvScrollWidget QPushButton:hover,DvScrollWidget QPushButton:hover,#ScrollLeftButton QPushButton:hover,#ScrollRightButton QPushButton:hover,#ScrollUpButton QPushButton:hover,#ScrollDownButton QPushButton:hover{background-color:#767676}.DvScrollWidget QPushButton:pressed,DvScrollWidget QPushButton:pressed,#ScrollLeftButton QPushButton:pressed,#ScrollRightButton QPushButton:pressed,#ScrollUpButton QPushButton:pressed,#ScrollDownButton QPushButton:pressed{background-color:#313131}#ScrollLeftButton,#ScrollRightButton,#ScrollUpButton,#ScrollDownButton{margin:0;min-width:16}#ScrollLeftButton{border-right:1 solid #272727;image:url('imgs/white/scroll-left.svg')}#ScrollRightButton{border-left:1 solid #272727;margin-left:3;image:url('imgs/white/scroll-right.svg')}#ScrollUpButton{image:url('imgs/white/scroll-up.svg')}#ScrollDownButton{image:url('imgs/white/scroll-down.svg')}#keyFrameNavigator{background:none;margin:0;padding:0}#keyFrameNavigator QToolButton{min-width:18}#keyFrameNavigator #PreviousKey{image:url('imgs/white/prevkey.svg')}#keyFrameNavigator #PreviousKey:hover{image:url('imgs/white/prevkey_over.svg')}#keyFrameNavigator #PreviousKey:disabled{image:url('imgs/white/prevkey_disabled.svg')}#keyFrameNavigator #NextKey{image:url('imgs/white/nextkey.svg')}#keyFrameNavigator #NextKey:hover{image:url('imgs/white/nextkey_over.svg')}#keyFrameNavigator #NextKey:disabled{image:url('imgs/white/nextkey_disabled.svg')}.treeview,QTreeWidget,QTreeView,#FunctionEditorTree{background-color:#343434;alternate-background-color:#393939;border:0;margin:0;outline:0}.treeview::item:selected,QTreeWidget::item:selected,QTreeView::item:selected,#FunctionEditorTree::item:selected{background-color:#5385a6;color:#fff}.treeview::branch:adjoins-item,QTreeWidget::branch:adjoins-item,QTreeView::branch:adjoins-item,#FunctionEditorTree::branch:adjoins-item{border-image:url('')}.treeview::branch:has-siblings,QTreeWidget::branch:has-siblings,QTreeView::branch:has-siblings,#FunctionEditorTree::branch:has-siblings{border-image:url('')}.treeview::branch:has-siblings:adjoins-item,QTreeWidget::branch:has-siblings:adjoins-item,QTreeView::branch:has-siblings:adjoins-item,#FunctionEditorTree::branch:has-siblings:adjoins-item{border-image:url('')}.treeview::branch:has-children:closed,QTreeWidget::branch:has-children:closed,QTreeView::branch:has-children:closed,#FunctionEditorTree::branch:has-children:closed{background:url('imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:open,QTreeWidget::branch:has-children:open,QTreeView::branch:has-children:open,#FunctionEditorTree::branch:has-children:open{background:url('imgs/white/treebranch-open.svg') no-repeat;background-position:center center;image:none}.treeview::branch:has-children:has-siblings:closed,QTreeWidget::branch:has-children:has-siblings:closed,QTreeView::branch:has-children:has-siblings:closed,#FunctionEditorTree::branch:has-children:has-siblings:closed{background:url('imgs/white/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:has-siblings:open,QTreeWidget::branch:has-children:has-siblings:open,QTreeView::branch:has-children:has-siblings:open,#FunctionEditorTree::branch:has-children:has-siblings:open{background:url('imgs/white/treebranch-open.svg') no-repeat;background-position:center center;border-image:none;image:none}QListView{outline:0;background:#343434;alternate-background-color:#393939}#TabBarContainer{background-color:#393939}.Button,QPushButton,.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{background-color:#696969;border:1 solid #484848;border-radius:2;color:#f3f3f3;margin:0;padding:3 15}.Button:hover,QPushButton:hover,.ComboBox:hover,#ViewerFpsSlider::sub-line:horizontal:hover,#ViewerFpsSlider::add-line:horizontal:hover,QComboBox:hover{background-color:#767676;border-color:#484848;color:#f3f3f3}.Button:pressed,QPushButton:pressed,#ViewerFpsSlider::sub-line:horizontal:pressed,#ViewerFpsSlider::add-line:horizontal:pressed{background-color:#313131;border-color:#2c2c2c;color:#f3f3f3}.Button:checked,QPushButton:checked{background-color:#313131;border-color:#2c2c2c;color:#f3f3f3}.Button:checked:hover,QPushButton:checked:hover{background-color:#363636}.Button:checked:hover:pressed,QPushButton:checked:hover:pressed{background:#313131}.Button:disabled,QPushButton:disabled,.ComboBox:disabled,#ViewerFpsSlider::sub-line:horizontal:disabled,#ViewerFpsSlider::add-line:horizontal:disabled,QComboBox:disabled{background-color:#555;border-color:#484848;color:#808080}#PushButton_NoPadding{padding:3}.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{padding:1 0 1 4;margin:1 0}.ComboBox::drop-down,QComboBox::drop-down{image:url('imgs/white/combo_downarrow.svg');image-position:center center;width:16}.ComboBox::drop-down:disabled,QComboBox::drop-down:disabled{image:url('imgs/white/combo_downarrow_disabled.svg')}.ComboBox QAbstractItemView,QComboBox QAbstractItemView{background-color:#484848;border:1 solid #272727;selection-background-color:#5385a6;selection-color:#fff}.LineEdit,QLineEdit,#TaskSheetItem,#tasksRemoveBox,#tasksAddBox{background-color:#2f2f2f;border:1 solid #2c2c2c;border-radius:2;color:#e6e6e6;selection-background-color:#5385a6;selection-color:#fff;padding:0 0 0 1}.LineEdit:focus,QLineEdit:focus,#TaskSheetItem:focus,#tasksRemoveBox:focus,#tasksAddBox:focus{background-color:#2f2f2f;border-color:#5385a6;color:#e6e6e6}.LineEdit:disabled,QLineEdit:disabled,#TaskSheetItem:disabled,#tasksRemoveBox:disabled,#tasksAddBox:disabled{background-color:#3b3b3b;border-color:#3a3a3a;color:#808080}.CheckBox,QCheckBox{color:#e6e6e6}.CheckBox:hover,QCheckBox:hover,.RadioButton:hover,QRadioButton:hover{color:#fff}.CheckBox:disabled,QCheckBox:disabled{color:#808080}.CheckBox::indicator,QMenu::indicator,QCheckBox::indicator,.GroupBox::indicator,QGroupBox::indicator{background-color:#2f2f2f;border:1 solid #2c2c2c;border-radius:2;height:9;padding:1;width:9}.CheckBox::indicator:hover,QMenu::indicator:hover,.CheckBox::indicator:checked:hover,QCheckBox::indicator:hover,.GroupBox::indicator:hover,QMenu::indicator:checked:hover,QCheckBox::indicator:checked:hover,.GroupBox::indicator:checked:hover,QGroupBox::indicator:hover,QGroupBox::indicator:checked:hover{background-color:#2f2f2f;border-color:#5385a6}.CheckBox::indicator:checked,QMenu::indicator:checked,QCheckBox::indicator:checked,.GroupBox::indicator:checked,QGroupBox::indicator:checked{background-color:#2f2f2f;border-color:#2c2c2c;image:url('imgs/white/checkmark.svg')}.CheckBox::indicator:checked:disabled,QMenu::indicator:checked:disabled,QCheckBox::indicator:checked:disabled,.GroupBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled{background-color:#3b3b3b;border-color:#3b3b3b;image:url('imgs/white/checkmark_disabled.svg')}.CheckBox::indicator:disabled,QMenu::indicator:disabled,QCheckBox::indicator:disabled,.GroupBox::indicator:disabled,QGroupBox::indicator:disabled{background-color:#3b3b3b;border-color:#3b3b3b}.RadioButton::indicator:unchecked,QRadioButton::indicator:unchecked,#CameraSettingsRadioButton_Small::indicator:unchecked{image:url('imgs/white/radiobutton_unchecked.svg');image-position:center center}.RadioButton::indicator:checked,QRadioButton::indicator:checked,#CameraSettingsRadioButton_Small::indicator:checked{image:url('imgs/white/radiobutton_checked.svg');image-position:center center}.GroupBox,QGroupBox{margin:6 0 0 0;padding:5 0}.GroupBox::title,QGroupBox::title{subcontrol-origin:margin;left:15;margin:-3 0 0 0;padding:0 3}.GroupBox::title:hover,QGroupBox::title:hover{color:#fff}.GroupBox::title:disabled,QGroupBox::title:disabled{color:#808080}.GroupBox::indicator,QGroupBox::indicator{subcontrol-origin:margin;margin-top:2}.GroupBox:disabled,QGroupBox:disabled{color:#808080}.Slider::groove:horizontal,QSlider::groove:horizontal{background-color:transparent;background-image:url('imgs/white/slider-groove.svg');background-position:center center;background-repeat:repeat-x;margin:0;height:20;min-height:20}.Slider::groove:horizontal:disabled,QSlider::groove:horizontal:disabled{background-image:url('imgs/white/slider-groove_disabled.svg')}.Slider::handle:horizontal,QSlider::handle:horizontal{width:10;margin:-2 -1;image:url('imgs/white/slider-handle.svg')}.Slider::handle:horizontal:disabled,QSlider::handle:horizontal:disabled{image:url('imgs/white/slider-handle_disabled.svg')}#IntPairField,#DoublePairField{qproperty-LightLineColor:#2c2c2c;qproperty-LightLineEdgeColor:#2c2c2c;qproperty-DarkLineColor:#2c2c2c;qproperty-MiddleLineColor:#2c2c2c;qproperty-HandleLeftPixmap:url("imgs/white/slider-handle.svg");qproperty-HandleRightPixmap:url("imgs/white/slider-handle.svg");qproperty-HandleLeftGrayPixmap:url("imgs/white/slider-handle_disabled.svg");qproperty-HandleRightGrayPixmap:url("imgs/white/slider-handle_disabled.svg")}#DirTreeView{background-color:#343434;alternate-background-color:#343434;border:1 solid #272727;border-right:0}DvItemViewerPanel{qproperty-TextColor:#e6e6e6;qproperty-AlternateBackground:#404040;qproperty-SelectedTextColor:#fff;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedItemBackground:#5385a6}#FileBrowser DvItemViewerPanel,#SceneCast DvItemViewerPanel{background-color:#484848}#FileBrowser #castFrame,#SceneCast #castFrame{border-top:1 solid #272727;border-right:1 solid #272727;border-bottom:1 solid #272727;margin:0}#FileBrowser QToolButton,#SceneCast QToolButton{padding:1}DvDirTreeView{qproperty-TextColor:#e6e6e6;qproperty-SelectedTextColor:#fff;qproperty-SelectedItemBackground:#5385a6;qproperty-FolderTextColor:#9fdaff;qproperty-SelectedFolderTextColor:#fff;alternate-background-color:#393939;background-color:#343434;border:1 solid #272727}#FileDoesNotExistLabel{color:#f00}#SceneCast QToolBar{border-top:1 solid #272727}#SceneCast QToolButton{margin:3 1 2 1;padding:1}#CastBrowser{border:0;margin:0}#FilmStrip QComboBox{border-radius:0;border-width:0}#FilmStrip QComboBox QAbstractItemView{background-color:#484848}#CleanupSettings #CleanupSettingsFrame{margin-top:2;margin-bottom:4}#CleanupSettings QGroupBox{margin-bottom:3}ParamsPage{qproperty-TextColor:#e6e6e6}#CameraSettingsButton{padding:2}#CameraSettingsRadioButton:hover{background:none}#CameraSettingsRadioButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#CameraSettingsRadioButton::indicator:unchecked{image:url('imgs/white/lock_off.svg')}#CameraSettingsRadioButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('imgs/white/lock_on.svg')}#CameraSettingsRadioButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#CameraSettingsDPI{color:#9fdaff}#CameraSettingsRadioButton_Small{padding:0}#CameraSettingsRadioButton_Small::indicator{background-color:transparent;border:0;height:21;margin:0;width:11}#ForceSquaredPixelButton{height:16;border:1 solid rgba(255,255,255,0);image:url('imgs/white/fsp_unchecked.svg');padding:2;width:16;margin:0}#ForceSquaredPixelButton:checked{image:url('imgs/white/fsp_checked.svg')}#OutputSettingsLabel{color:#9fdaff}PencilTestPopup{min-height:730px;min-width:512px}#MatchLineButton{background-color:#6e6e6e}#MatchLineButton:checked{background-color:#949494;border:2 solid #5385a6;border-radius:2}#LargeSizedText{font-size:17}#StartupLabel{padding:3}#StartupLabel:hover{background:#626262}QStatusBar{background-color:#c0c0c0}QStatusBar::item{border:0}QStatusBar QLabel{background-color:#c0c0c0}QStatusBar #StatusBarLabel{background-color:#fff;padding:1 3}#TitleTxtLabel{color:#9fdaff}#StyleEditor QPushButton{margin:2 1;padding:0}#StyleEditor #TabBarContainer{margin-left:-4}#StyleEditor #bottomWidget{border-top:1 solid #272727;padding:3 2 8 3}#StyleEditor #bottomWidget QPushButton{padding:3 5}#StyleEditorTabBar::tab::first{border-left:1 solid #272727}#HexagonalColorWheel{qproperty-BGColor:#484848}#colorSlider::groove:horizontal{height:1;border-image:none}#colorSlider::handle:horizontal{width:8;margin:-8 -4}#colorSliderAddButton,#colorSliderSubButton{background:none;border-color:transparent;image-position:center center;min-height:16;padding:0;min-width:18}#colorSliderAddButton{image:url('imgs/white/scroll-right.svg')}#colorSliderSubButton{image:url('imgs/white/scroll-left.svg')}#PlainColorPageParts{border-bottom:1 solid #272727}#PlainColorPageParts QLineEdit{max-width:35}PaletteViewer DvScrollWidget QPushButton{border-top:0;margin-bottom:1;max-width:15;min-width:15}PaletteViewer DvScrollWidget #ScrollLeftButton{border-radius:0;margin-bottom:1;max-width:16;min-width:16}PaletteViewer DvScrollWidget #ScrollRightButton{border-radius:0;margin-left:1;margin-bottom:1;max-width:16;min-width:16}PaletteViewer QToolBar{background:none;border-bottom:1 solid #272727;padding:0;margin:0}PaletteViewer QToolBar::separator:horizontal{margin:0}PaletteViewer QToolBar QToolButton{margin:0 0 1 0;padding:1 0 2 0}#PageViewer{qproperty-TextColor:#e6e6e6}#PaletteLockButton{border-radius:0;margin:0 0 1 1}#PaletteLockButton:checked{background-color:#C34040;border-color:#C34040}#PaletteLockButton:checked:hover{background-color:#d57a7a;border-color:#d57a7a}#WordButton{padding-right:0;padding-left:0}QDialog{background-color:#484848}QDialog #dialogButtonFrame{background-color:#3e3e3e;border-top:1 solid #272727}QDialog #dialogButtonFrame QPushButton{border-color:#3e3e3e;outline:0}QDialog #dialogButtonFrame QPushButton:focus{background-color:#5385a6;border-color:#3e3e3e;color:#fff}QDialog #dialogButtonFrame QPushButton:focus:hover{background-color:#6c98b6}QDialog #dialogButtonFrame QPushButton:focus:pressed{background-color:#313131;border-color:#2c2c2c;color:#f3f3f3}#SceneSettings QLabel{color:#9fdaff}#PreferencesPopup QListWidget{background-color:#343434;alternate-background-color:#343434;border:1 solid #272727;font-size:13}#PreferencesPopup QListWidget::item{border:0;padding:3}#PreferencesPopup QListWidget::item:hover{color:#e6e6e6;background-color:rgba(255,255,255,0.15)}#PreferencesPopup QListWidget::item:selected{background-color:#5385a6;color:#fff}#ShortcutTree{border:1 solid #272727}#ShortcutTree::item{padding:1 0}#ShortcutTree QScrollBar:vertical{width:16;margin-right:-1}ProjectPopup QLabel{color:#9fdaff}#GearButton{qproperty-icon:url('imgs/white/gear.svg')}#SubfolderButton{qproperty-icon:url('imgs/white/subfolder.svg')}SchematicViewer{qproperty-TextColor:#e6e6e6;qproperty-VerticalLineColor:#222;qproperty-LevelColumnColor:#4C6E4C;qproperty-VectorColumnColor:#7B7B4C;qproperty-ChildColumnColor:#6A526B;qproperty-FullcolorColumnColor:#657A96;qproperty-FxColumnColor:#56553C;qproperty-PaletteColumnColor:#3A655F;qproperty-MeshColumnColor:#684D86;qproperty-ReferenceColumnColor:#616161;qproperty-TableColor:#62628c;qproperty-ActiveCameraColor:#2d7dca;qproperty-OtherCameraColor:#6c797b;qproperty-GroupColor:#3b6e9c;qproperty-PegColor:#9f6e3c;qproperty-SplineColor:#6a9d1c;qproperty-ActiveOutputColor:#2d7dca;qproperty-OtherOutputColor:#6c797b;qproperty-XsheetColor:#62628c;qproperty-NormalFxColor:#6a7e96;qproperty-MacroFxColor:#815c79;qproperty-ImageAdjustFxColor:#656287;qproperty-LayerBlendingFxColor:#4f757d;qproperty-MatteFxColor:#ae7171;qproperty-SchematicPreviewButtonBgOnColor:#c8c864;qproperty-SchematicPreviewButtonOnImage:url('imgs/white/x_prev_eye_on.svg');qproperty-SchematicPreviewButtonBgOffColor:#616161;qproperty-SchematicPreviewButtonOffImage:url('imgs/white/x_prev_eye_off.svg');qproperty-SchematicCamstandButtonBgOnColor:#eb906b;qproperty-SchematicCamstandButtonOnImage:url('imgs/white/x_table_view_on.svg');qproperty-SchematicCamstandButtonTranspImage:url('imgs/white/x_table_view_transp.svg');qproperty-SchematicCamstandButtonBgOffColor:#616161;qproperty-SchematicCamstandButtonOffImage:url('imgs/white/x_table_view_off.svg')}#SchematicBottomFrame{background-color:#484848;border:0;margin:0;padding:0}#SchematicBottomFrame QToolBar::separator:horizontal{margin:0}#SchematicBottomFrame QToolBar QToolButton{padding:0;margin:2}#SchematicSceneViewer{background-color:#3b3b3b;border-bottom:1 solid #272727}#FxSettingsTabBar::tab{border-top:1 solid #272727}#FxSettingsTabBar::tab::first,#FxSettingsTabBar::tab::only-one{border-left:1 solid #272727}FxSettings QToolBar{border-top:1 solid #272727;border-right:1 solid #272727;border-left:1 solid #272727;min-height:23;padding:3 0}FxSettings QToolBar QToolBar{border:0}#FxSettingsLabel{color:#a0e680}#FxSettingsHelpButton{background-color:#80a0dc;color:#000;padding-top:0;padding-bottom:0}#FxSettingsHelpButton:hover{background-color:#a8bee7}#ScriptConsole{font-family:'Courier New',monospace;border:0;color:#000000;padding:3}#ScriptConsole QFrame{background-color:#dcdcdc}#ScriptConsole TPanelTitleBar{background-color:#393939}#TaskSheetItemLabel{color:#e6e6e6}#Tasks QToolBar{border-bottom:1 solid #272727;margin:0;padding:0}#Tasks QToolBar QToolButton{margin:2 2 3 2}#ToolBar QToolBar{padding-left:2}#ToolOptions TPanelTitleBar{border-right:1 solid #272727;border-bottom:0}#CommandBar TPanelTitleBar{border-right:1 solid #272727;border-bottom:0}IconViewField{qproperty-ThicknessPixmap:url("imgs/white/selectiontool_thickness.svg")}#EditToolLockButton{spacing:0}#EditToolLockButton:hover{background:none}#EditToolLockButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#EditToolLockButton::indicator:unchecked{image:url('imgs/white/lock_off.svg')}#EditToolLockButton::indicator:checked{background-color:#C34040;border-color:#C34040;image:url('imgs/white/lock_on.svg')}#EditToolLockButton::indicator:checked:hover{background-color:#d57a7a;border-color:#d57a7a}PopupButton::menu-indicator{border-left:0;height:17;image:url('imgs/white/combo_downarrow.svg');width:10}PopupButton::menu-indicator:hover{image:url('imgs/white/combo_downarrow.svg')}PopupButton::menu-indicator:disabled{image:url('imgs/white/combo_downarrow_disabled.svg')}#Cap,#Join{padding:0 4 0 -8;max-width:32;min-width:32}#Cap QMenu,#Join QMenu{max-width:28;min-width:28}#Cap QMenu::item,#Join QMenu::item{max-width:28;min-width:28;padding:0}QToolBar#MediumPaddingToolBar QToolButton{padding-left:3;padding-right:3}QToolBar#WidePaddingToolBar QToolButton{padding-left:6;padding-right:6}#CommandBar{margin:0;padding:0;border:0}#CommandBar::separator:horizontal{margin-right:3;margin-left:3}#expandButton:checked{background-color:transparent;border-color:transparent;color:#e6e6e6}#expandButton:checked:hover{background-color:#767676;border-color:#767676}#expandButton:checked:pressed{background-color:#313131;border-color:#2c2c2c}#ComboViewerPanel Toolbar{border-bottom:1 solid #272727}#ComboViewerPanel Toolbar::separator:horizontal{margin:0 0 0 2}#ComboViewerPanel Toolbar QToolButton{margin:2 0 3 2}#ComboViewerToolOptions{border-bottom:1 solid #272727}#ComboViewer #ToolBarContainer,#ViewerPanel #ToolBarContainer,FlipBook #ToolBarContainer{background-color:transparent;border-top:2 solid #272727;border-bottom:1 solid #272727;padding-right:-1}#flipCustomize{margin-left:3}#flipCustomize::menu-button{background-color:transparent;width:35}#flipCustomize::menu-arrow{image:none}QToolBar#FlipConsolePlayToolBar::separator:horizontal{margin:0 3}QToolBar#FlipConsolePlayToolBar QToolButton{margin-top:2;margin-bottom:2;height:16;padding-left:1;padding-right:1}#ViewerFpsSlider{background-color:transparent;background-image:url('imgs/white/slider-groove.svg');background-position:center center;background-repeat:repeat-x;border:0;height:19;margin:0 3 0 37;max-width:300;min-width:0}#ViewerFpsSlider::sub-line:horizontal{subcontrol-origin:absolute;background-color:#696969;border:1 solid #484848;border-top-left-radius:2;border-bottom-left-radius:2;height:16;left:-33;width:14}#ViewerFpsSlider::add-line:horizontal{subcontrol-position:left;background-color:#696969;border:1 solid #484848;border-top-right-radius:2;border-bottom-right-radius:2;left:18;height:16;image-position:center center;width:13}#ViewerFpsSlider::handle::horizontal{background-color:#a1a1a1;border:1 solid #a1a1a1;border-radius:2;margin:2 0 3 0;min-width:9;width:9;max-width:9}FlipSlider{qproperty-PBHeight:15;qproperty-PBOverlay:url('imgs/white/flipslider.svg');qproperty-PBColorMarginLeft:1;qproperty-PBColorMarginTop:2;qproperty-PBColorMarginRight:1;qproperty-PBColorMarginBottom:2;qproperty-PBMarker:url('imgs/white/flipmarker.svg');qproperty-PBMarkerMarginLeft:3;qproperty-PBMarkerMarginRight:3;qproperty-notStartedColor:rgba(205,101,101,0.78);qproperty-startedColor:#1abc3f;qproperty-baseColor:#2f2f2f;qproperty-finishedColor:#2f2f2f}Ruler{qproperty-ParentBGColor:#484848;qproperty-ScaleColor:#e6e6e6}#RulerToolOptionValues{color:#000}#xsheetArea,#ScrollArea{background-color:#343434;border:0}#xsheetScrollArea{border:0}#cornerWidget QToolButton{padding:0}#xsheetColumnAreaMenu_Preview{background-color:#E6E678}#xsheetColumnAreaMenu_Lock{background-color:#F5F5F5}#xsheetColumnAreaMenu_Camstand{background-color:#FFA480}#xsheetColumnAreaMenu_Preview,#xsheetColumnAreaMenu_Lock,#xsheetColumnAreaMenu_Camstand{color:#000}#noteTextEdit{color:#000}XsheetViewer{qproperty-TextColor:#e6e6e6;qproperty-BGColor:#3b3b3b;qproperty-LightLineColor:#2c2c2c;qproperty-MarkerLineColor:#1E96C4;qproperty-VerticalLineColor:#222;qproperty-VerticalLineHeadColor:#808080;qproperty-PreviewFrameTextColor:#9fdaff;qproperty-CurrentRowBgColor:#506082;qproperty-OnionSkinAreaBgColor:#363636;qproperty-EmptyColumnHeadColor:#626262;qproperty-SelectedColumnTextColor:#E66464;qproperty-EmptyCellColor:#404040;qproperty-NotEmptyColumnColor:#484848;qproperty-SelectedEmptyCellColor:#6c6c6c;qproperty-LevelColumnColor:#4C6E4C;qproperty-LevelColumnBorderColor:#8FB38F;qproperty-SelectedLevelColumnColor:#678667;qproperty-VectorColumnColor:#7B7B4C;qproperty-VectorColumnBorderColor:#BBBB9A;qproperty-SelectedVectorColumnColor:#949466;qproperty-ChildColumnColor:#6A526B;qproperty-ChildColumnBorderColor:#B1A3B3;qproperty-SelectedChildColumnColor:#816e82;qproperty-FullcolorColumnColor:#657A96;qproperty-FullcolorColumnBorderColor:#9EB8BB;qproperty-SelectedFullcolorColumnColor:#8895a6;qproperty-FxColumnColor:#56553C;qproperty-FxColumnBorderColor:#95958A;qproperty-SelectedFxColumnColor:#6f6e56;qproperty-ReferenceColumnColor:#616161;qproperty-ReferenceColumnBorderColor:#A2A2A2;qproperty-SelectedReferenceColumnColor:#7a7a7a;qproperty-PaletteColumnColor:#3A655F;qproperty-PaletteColumnBorderColor:#86ACA7;qproperty-SelectedPaletteColumnColor:#52807a;qproperty-MeshColumnColor:#684D86;qproperty-MeshColumnBorderColor:#BA92EF;qproperty-SelectedMeshColumnColor:#82689e;qproperty-SoundTextColumnColor:#c8c8c8;qproperty-SoundTextColumnBorderColor:#8c8c8c;qproperty-SelectedSoundTextColumnColor:#e2e2e2;qproperty-SoundColumnColor:#657456;qproperty-SoundColumnBorderColor:#A0AF7D;qproperty-SelectedSoundColumnColor:#7e8b72;qproperty-SoundColumnHlColor:#34FE5E;qproperty-SoundColumnTrackColor:#B6C29D;qproperty-ColumnHeadPastelizer:#000;qproperty-SelectedColumnHead:#506082;qproperty-LightLightBGColor:#404040;qproperty-LightBGColor:#f0f0f0;qproperty-DarkBGColor:#e1e1e1;qproperty-DarkLineColor:#969696;qproperty-XsheetColumnNameBgColor:rgba(0,0,0,0);qproperty-XsheetDragBarHighlightColor:rgba(255,255,255,0.5);qproperty-XsheetPreviewButtonBgOnColor:#c8c864;qproperty-XsheetPreviewButtonOnImage:url('imgs/white/x_prev_eye_on.svg');qproperty-XsheetPreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetPreviewButtonOffImage:url('imgs/white/x_prev_eye_off.svg');qproperty-XsheetCamstandButtonBgOnColor:#eb906b;qproperty-XsheetCamstandButtonOnImage:url('imgs/white/x_table_view_on.svg');qproperty-XsheetCamstandButtonTranspImage:url('imgs/white/x_table_view_transp.svg');qproperty-XsheetCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetCamstandButtonOffImage:url('imgs/white/x_table_view_off.svg');qproperty-XsheetLockButtonBgOnColor:rgba(255,255,255,0.3);qproperty-XsheetLockButtonOnImage:url('imgs/white/x_lock_on.svg');qproperty-XsheetLockButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetLockButtonOffImage:url('imgs/white/x_lock_off.svg');qproperty-XsheetConfigButtonBgColor:rgba(255,255,255,0);qproperty-XsheetConfigButtonImage:url('imgs/white/x_config.svg');qproperty-TimelinePreviewButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOnImage:url('imgs/white/timeline_toggle_on.svg');qproperty-TimelinePreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOffImage:url('imgs/white/timeline_toggle_off.svg');qproperty-TimelineCamstandButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOnImage:url('imgs/white/timeline_toggle_on.svg');qproperty-TimelineCamstandButtonTranspImage:url('imgs/white/timeline_toggle_transp.svg');qproperty-TimelineCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOffImage:url('imgs/white/timeline_toggle_off.svg');qproperty-TimelineLockButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOnImage:url('imgs/white/timeline_toggle_on.svg');qproperty-TimelineLockButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOffImage:url('imgs/white/timeline_toggle_off.svg');qproperty-TimelineConfigButtonBgColor:rgba(255,255,255,0);qproperty-TimelineConfigButtonImage:url('imgs/white/timeline_config.svg');qproperty-LayerHeaderPreviewImage:url('imgs/white/layer_header_prev_eye.svg');qproperty-LayerHeaderPreviewOverImage:url('imgs/white/layer_header_prev_eye_over.svg');qproperty-LayerHeaderCamstandImage:url('imgs/white/layer_header_table_view.svg');qproperty-LayerHeaderCamstandOverImage:url('imgs/white/layer_header_table_view_over.svg');qproperty-LayerHeaderLockImage:url('imgs/white/lock_on.svg');qproperty-LayerHeaderLockOverImage:url('imgs/white/lock_on_over.svg')}#XSheetToolbar{margin:0;padding:0;border:0}#XSheetToolbar QToolButton{padding:0;margin:4 1;min-height:19;height:19}#XSheetToolbar::separator:horizontal{margin:0 4}#FunctionEditor QToolBar{border-bottom:1 solid #272727}#FunctionEditor QToolBar QToolBar{border:0}#FunctionEditor QToolBar QLabel{margin-left:5}#FunctionEditor QToolBar QToolButton{height:18}#FunctionEditorTree{border-top:1 solid #272727}FunctionTreeView{qproperty-TextColor:#e6e6e6;qproperty-CurrentTextColor:#E66464}FunctionPanel{qproperty-BGColor:#3b3b3b;qproperty-ValueLineColor:#2f2f2f;qproperty-FrameLineColor:#2f2f2f;qproperty-OtherCurvesColor:#888;qproperty-RulerBackground:#333;qproperty-TextColor:#e6e6e6;qproperty-SubColor:#000;qproperty-SelectedColor:#FFA500}SpreadsheetViewer{qproperty-LightLightBGColor:#404040;qproperty-CurrentRowBgColor:#506082;qproperty-LightLineColor:#2c2c2c;qproperty-MarkerLineColor:#1E96C4;qproperty-BGColor:#484848;qproperty-VerticalLineColor:#222;qproperty-KeyFrameColor:#995d1d;qproperty-KeyFrameBorderColor:#c9b04b;qproperty-SelectedKeyFrameColor:#be772b;qproperty-InBetweenColor:#666250;qproperty-InBetweenBorderColor:#cdcec8;qproperty-SelectedInBetweenColor:#7d7a6c;qproperty-SelectedEmptyColor:#6c6c6c;qproperty-SelectedSceneRangeEmptyColor:#757575;qproperty-TextColor:#e6e6e6;qproperty-ColumnHeaderBorderColor:#808080;qproperty-SelectedColumnTextColor:#E66464}#ExpressionField{background-color:#e6e6e6;border:1 solid #333;margin:0}#FunctionSegmentViewerLinkButton{background-image:url('imgs/white/segment_unlinked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:hover{background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:checked{background-image:url('imgs/white/segment_linked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:disabled{background-image:url('imgs/white/segment_disabled.svg');background-repeat:no-repeat} \ No newline at end of file diff --git a/stuff/config/qss/Default/less/Default.less b/stuff/config/qss/Default/less/Default.less index d9858bc..2c6179a 100644 --- a/stuff/config/qss/Default/less/Default.less +++ b/stuff/config/qss/Default/less/Default.less @@ -310,6 +310,7 @@ @xsheet-VerticalLineHead-color: lighten(@bg, 21.9608); @xsheet-PreviewFrameText-color: @label-title; @xsheet-CurrentRowBG-color: #506082; +@xsheet-OnionSkinAreaBG-color: darken(@bg, 7); @xsheet-EmptyColumnHead-color: lighten(@bg, 10.1961); @xsheet-SelectedColumnText-color: #E66464; @@ -455,16 +456,17 @@ @schematic-FxColumn-color: @xsheet-FxColumn-color; @schematic-PaletteColumn-color: @xsheet-PaletteColumn-color; @schematic-MeshColumn-color: @xsheet-MeshColumn-color; +@schematic-ReferenceColumn-color: @xsheet-ReferenceColumn-color; @schematic-PreviewButtonBgOn-color: @xsheet-PreviewButtonBgOn-color; @schematic-PreviewButtonOnImage: @xsheet-PreviewButtonOnImage; -@schematic-PreviewButtonBgOff-color: fade(@xsheet-PreviewButtonBgOn-color, 50%); +@schematic-PreviewButtonBgOff-color: @xsheet-ReferenceColumn-color; @schematic-PreviewButtonOffImage: @xsheet-PreviewButtonOffImage; @schematic-CamstandButtonBgOn-color: @xsheet-CamstandButtonBgOn-color; @schematic-CamstandButtonOnImage: @xsheet-CamstandButtonOnImage; @schematic-CamstandButtonTranspImage: @xsheet-CamstandButtonTranspImage; -@schematic-CamstandButtonBgOff-color: fade(@xsheet-CamstandButtonBgOn-color, 50%); +@schematic-CamstandButtonBgOff-color: @xsheet-ReferenceColumn-color; @schematic-CamstandButtonOffImage: @xsheet-CamstandButtonOffImage; // ----------------------------------------------------------------------------- diff --git a/stuff/config/qss/Default/less/layouts/schematic.less b/stuff/config/qss/Default/less/layouts/schematic.less index fe5457f..689b137 100644 --- a/stuff/config/qss/Default/less/layouts/schematic.less +++ b/stuff/config/qss/Default/less/layouts/schematic.less @@ -13,6 +13,7 @@ SchematicViewer { qproperty-FxColumnColor: @schematic-FxColumn-color; qproperty-PaletteColumnColor: @schematic-PaletteColumn-color; qproperty-MeshColumnColor: @schematic-MeshColumn-color; + qproperty-ReferenceColumnColor: @schematic-ReferenceColumn-color; qproperty-TableColor: @schematic-TableColor; qproperty-ActiveCameraColor: @schematic-ActiveCameraColor; diff --git a/stuff/config/qss/Default/less/layouts/xsheet.less b/stuff/config/qss/Default/less/layouts/xsheet.less index a616d97..1e3c46b 100644 --- a/stuff/config/qss/Default/less/layouts/xsheet.less +++ b/stuff/config/qss/Default/less/layouts/xsheet.less @@ -58,6 +58,7 @@ XsheetViewer { qproperty-VerticalLineHeadColor: @xsheet-VerticalLineHead-color; qproperty-PreviewFrameTextColor: @xsheet-PreviewFrameText-color; qproperty-CurrentRowBgColor: @xsheet-CurrentRowBG-color; + qproperty-OnionSkinAreaBgColor: @xsheet-OnionSkinAreaBG-color; qproperty-EmptyColumnHeadColor: @xsheet-EmptyColumnHead-color; qproperty-SelectedColumnTextColor: @xsheet-SelectedColumnText-color; diff --git a/stuff/config/qss/Default/less/themes/Light.less b/stuff/config/qss/Default/less/themes/Light.less index d1ce6fe..17697c8 100644 --- a/stuff/config/qss/Default/less/themes/Light.less +++ b/stuff/config/qss/Default/less/themes/Light.less @@ -244,6 +244,7 @@ @xsheet-VerticalLineHead-color: darken(@bg, 28); @xsheet-PreviewFrameText-color: #000eb6; @xsheet-CurrentRowBG-color: #B5C0D0; +@xsheet-OnionSkinAreaBG-color: lighten(@bg, 2.12); @xsheet-EmptyColumnHead-color: @bg; @xsheet-SelectedColumnText-color: rgb(158, 0, 0); diff --git a/stuff/config/qss/Light/Light.qss b/stuff/config/qss/Light/Light.qss index 89494bf..3686cf5 100644 --- a/stuff/config/qss/Light/Light.qss +++ b/stuff/config/qss/Light/Light.qss @@ -1 +1 @@ -.button-show,#LoadLevelShowButton,#CleanupSettingsShowButton,#OutputSettingsShowButton,#FxSettingsPreviewShowButton{image:url('../Default/imgs/black/plus.svg');image-position:center center;margin:0;padding:1;min-width:10;min-height:10}.button-show:checked,#LoadLevelShowButton:checked,#CleanupSettingsShowButton:checked,#OutputSettingsShowButton:checked,#FxSettingsPreviewShowButton:checked{background-color:#5a5a5a;border-color:#454545;image:url('../Default/imgs/black/minus.svg')}.button-show:checked:pressed,#LoadLevelShowButton:checked:pressed,#CleanupSettingsShowButton:checked:pressed,#OutputSettingsShowButton:checked:pressed,#FxSettingsPreviewShowButton:checked:pressed{background-color:#e1e1e1;border-color:#525252}.button-show:checked:hover,#LoadLevelShowButton:checked:hover,#CleanupSettingsShowButton:checked:hover,#OutputSettingsShowButton:checked:hover,#FxSettingsPreviewShowButton:checked:hover{background-color:#5f5f5f}.button-tool,QToolButton,#CameraSettingsRadioButton::indicator,#ForceSquaredPixelButton,#SchematicBottomFrame QToolBar QToolButton,#EditToolLockButton::indicator,#flipCustomize{background-color:rgba(255,255,255,0);border:1 solid rgba(255,255,255,0);border-radius:2;color:#000;margin:1;padding:0}.button-tool:hover,QToolButton:hover,#CameraSettingsRadioButton::indicator:hover,#ForceSquaredPixelButton:hover,#colorSliderAddButton:hover,#colorSliderSubButton:hover,#SchematicBottomFrame QToolBar QToolButton:hover,#EditToolLockButton::indicator:hover,#flipCustomize:hover{background-color:#bbb;border-color:#525252;color:#000}.button-tool:pressed,QToolButton:pressed,#CameraSettingsRadioButton::indicator:pressed,#ForceSquaredPixelButton:pressed,#colorSliderAddButton:pressed,#colorSliderSubButton:pressed,#SchematicBottomFrame QToolBar QToolButton:pressed,#EditToolLockButton::indicator:pressed,#flipCustomize:pressed{background-color:#e1e1e1;border-color:#525252;color:#000}.button-tool:checked,QToolButton:checked,#CameraSettingsRadioButton::indicator:checked,#ForceSquaredPixelButton:checked,#SchematicBottomFrame QToolBar QToolButton:checked,#EditToolLockButton::indicator:checked,#flipCustomize:checked{background-color:#5a5a5a;border-color:#454545;color:#c0c0c0}.button-tool:checked:hover,QToolButton:checked:hover,#CameraSettingsRadioButton::indicator:checked:hover,#ForceSquaredPixelButton:checked:hover,#SchematicBottomFrame QToolBar QToolButton:checked:hover,#EditToolLockButton::indicator:checked:hover,#flipCustomize:checked:hover{background-color:#6e6e6e;border-color:#454545}.button-tool:disabled,QToolButton:disabled,#CameraSettingsRadioButton::indicator:disabled,#ForceSquaredPixelButton:disabled,#SchematicBottomFrame QToolBar QToolButton:disabled,#EditToolLockButton::indicator:disabled,#flipCustomize:disabled{color:rgba(0,0,0,0.466)}.button-flat,PaletteViewer QToolBar QToolButton{background-color:none;border:0;border-radius:0;margin:0}.button-flat:hover,PaletteViewer QToolBar QToolButton:hover{background-color:#bbb}.button-flat:pressed,PaletteViewer QToolBar QToolButton:pressed{background-color:#404040}.frame,.GroupBox,#LoadLevelFrame,#PsdSettingsGroupBox,#CleanupSettingsFrame,#OutputSettingsBox,#OutputSettingsCameraBox,#SolidLineFrame,#FunctionParametersPanel,QGroupBox{border:1 solid #404040;border-radius:2}.tab-container,#TabBarContainer{background-color:transparent;qproperty-BottomAboveLineColor:#6c6c6c;qproperty-BottomBelowLineColor:#404040}.tab-flat,#StyleEditorTabBar::tab,#PaletteTabBar::tab,#FxSettingsTabBar::tab{background-color:#5a5a5a;border-right:1 solid #404040;border-bottom:1 solid #404040;color:#c0c0c0;padding:3 4 3 4}.tab-flat:hover,#StyleEditorTabBar::tab:hover,#PaletteTabBar::tab:hover,#FxSettingsTabBar::tab:hover{background-color:#6e6e6e;color:#fff}.tab-flat:selected,#StyleEditorTabBar::tab:selected,#PaletteTabBar::tab:selected,#FxSettingsTabBar::tab:selected{background-color:#808080;color:#000;border-bottom-color:#808080}.tab-flat:only-one,#StyleEditorTabBar::tab:only-one,#PaletteTabBar::tab:only-one,#FxSettingsTabBar::tab:only-one{margin:0}.tab-round{background-color:#5a5a5a;border-top:1 solid #404040;border-right:1 solid #404040;border-left:1 solid #404040;border-bottom:1 solid #404040;color:#c0c0c0;margin:3 -1 0 0;padding:2 7 1 7}.tab-round:hover{background-color:#6e6e6e;color:#fff}.tab-round:selected{background-color:#808080;border-top-right-radius:2;border-top-left-radius:2;border-bottom-color:#808080;color:#000;margin:1 -1 -1 0;padding:2 7 2 7}.tab-round:only-one{margin:1 0 0 0;padding:3 7 3 7}.tab-round:last{margin-right:0;border-top-right-radius:2}.tab-round:first{border-top-left-radius:2}QWidget{background-color:#808080;color:#000}QWidget:disabled{color:rgba(0,0,0,0.466)}QFrame{border:0;margin:0;padding:0}QToolTip,#helpToolTip{background-color:#fff;border:1 solid #000;color:#000;padding:1 1}#DockSeparator,QMainWindow::separator,QSplitter::handle{background-color:#272727;height:4;width:4}#TDockPlaceholder{background-color:#F77272}TPanel{background-color:#272727}#TopBar{background:#808080;border:0;border-bottom:1 solid #404040;height:21}#TopBar #EditToolLockButton{background:#808080;spacing:0}#TopBar #EditToolLockButton::indicator{background:none;border:none;height:18;margin:1 2 0 0;padding-left:0;padding-right:0}#TopBarTabContainer{background-color:#808080;margin-bottom:1}#StackedMenuBar{border:0;margin:0;padding:0}QMenuBar{background-color:#808080;border:0}QMenuBar::item{background-color:#808080;border-left:1 solid #808080;margin:0;padding:3 5}QMenuBar::item:selected{background-color:#9f9f9f;color:#000}QMenuBar::item:pressed{background-color:#225baf;color:#FFFFFF}#TopBarTab{margin:0;padding:0}#TopBarTab::tab{background-color:#5a5a5a;border-top:1 solid #404040;border-right:1 solid #404040;color:#afafaf;margin:0 0 0 0;padding:2 8 3 8}#TopBarTab::tab:hover{background-color:#6e6e6e;color:#fff}#TopBarTab::tab:selected{background-color:#9a9a9a;color:#000}#TopBarTab::tab:first{border-left:1 solid #404040}#TopBarTab::tab:last{border-right:1 solid #404040}QMenu{background-color:#949494;border:1 solid #404040;padding:2 0}QMenu::item{padding:3 28}QMenu::item:selected{background-color:#225baf;color:#FFFFFF}QMenu::item:checked{color:#000}QMenu::item:checked:selected{background-color:#225baf;color:#FFFFFF}QMenu::item:disabled{background:none;color:rgba(0,0,0,0.466)}QMenu::item:disabled:selected{border-color:transparent}QMenu::separator{border-top:1 solid #6e6e6e;height:0;margin:2 0}QMenu::icon{border-radius:2;margin:0 0 0 3;padding:1}QMenu::icon:checked{background-color:#225baf}QMenu::indicator{margin-left:7}TPanelTitleBar{background-color:#5a5a5a;border-color:#404040;border-style:solid;border-width:0 0 1 0;height:20;min-height:20;qproperty-TitleColor:#c0c0c0;qproperty-ActiveTitleColor:#fff;qproperty-BorderPixmap:url('none');qproperty-ActiveBorderPixmap:url('../Default/imgs/black/none');qproperty-FloatBorderPixmap:url('none');qproperty-FloatActiveBorderPixmap:url('../Default/imgs/black/none')}QAbstractScrollArea::corner{background-color:#6e6e6e}QScrollBar{background-color:#6e6e6e;border:0}QScrollBar:horizontal{height:16;margin:0}QScrollBar:vertical{margin:0;width:16}QScrollBar::handle{border:1 solid #555;border-radius:2}QScrollBar::handle:horizontal:hover,QScrollBar::handle:vertical:hover{background-color:#b3b3b3;border-color:#404040}QScrollBar::handle:horizontal:pressed,QScrollBar::handle:vertical:pressed{background-color:#c7c7c7;border-color:#404040}QScrollBar::handle:horizontal{background-color:#9f9f9f;margin:2 16;min-width:20}QScrollBar::handle:vertical{background-color:#9f9f9f;margin:16 2;min-height:20}QScrollBar::add-line{subcontrol-origin:margin;border:0}QScrollBar::add-line:horizontal{subcontrol-position:right;background-color:#6e6e6e;margin:0;width:16}QScrollBar::add-line:vertical{subcontrol-position:bottom;background-color:#6e6e6e;margin:0;height:16}QScrollBar::sub-line{border:0;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{subcontrol-position:left;background-color:#6e6e6e;margin:0;width:16}QScrollBar::sub-line:vertical{subcontrol-position:top;background-color:#6e6e6e;margin:0;height:16}QScrollBar::up-arrow:vertical{image:url('../Default/imgs/black/scroll-up.svg');image-position:center center}QScrollBar::up-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::down-arrow:vertical{image:url('../Default/imgs/black/scroll-down.svg');image-position:center center}QScrollBar::down-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::left-arrow:horizontal{image:url('../Default/imgs/black/scroll-left.svg');image-position:center center}QScrollBar::left-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::right-arrow:horizontal{image:url('../Default/imgs/black/scroll-right.svg');image-position:center center}QScrollBar::right-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::sub-page:horizontal,QScrollBar::add-page:horizontal,QScrollBar::sub-page:vertical,QScrollBar::add-page:vertical{background:none}QToolBar{padding:0}QToolBar::separator:horizontal{border-left:1 solid #404040;margin:0 1;width:0}QToolBar::separator:vertical{border-top:1 solid #404040;height:0;margin:1 0}QToolBar QLabel{margin-top:1}QToolBar QToolBar{border:0}QToolButton::menu-indicator{image:none}QToolButton::menu-button{border-image:none}.DvScrollWidget QPushButton,DvScrollWidget QPushButton,#ScrollLeftButton QPushButton,#ScrollRightButton QPushButton,#ScrollUpButton QPushButton,#ScrollDownButton QPushButton{background-color:#a6a6a6;border:0 solid red;border-radius:0;padding:0;max-width:16}.DvScrollWidget QPushButton:hover,DvScrollWidget QPushButton:hover,#ScrollLeftButton QPushButton:hover,#ScrollRightButton QPushButton:hover,#ScrollUpButton QPushButton:hover,#ScrollDownButton QPushButton:hover{background-color:#bbb}.DvScrollWidget QPushButton:pressed,DvScrollWidget QPushButton:pressed,#ScrollLeftButton QPushButton:pressed,#ScrollRightButton QPushButton:pressed,#ScrollUpButton QPushButton:pressed,#ScrollDownButton QPushButton:pressed{background-color:#e1e1e1}#ScrollLeftButton,#ScrollRightButton,#ScrollUpButton,#ScrollDownButton{margin:0;min-width:16}#ScrollLeftButton{border-right:1 solid #404040;image:url('../Default/imgs/black/scroll-left.svg')}#ScrollRightButton{border-left:1 solid #404040;margin-left:3;image:url('../Default/imgs/black/scroll-right.svg')}#ScrollUpButton{image:url('../Default/imgs/black/scroll-up.svg')}#ScrollDownButton{image:url('../Default/imgs/black/scroll-down.svg')}#keyFrameNavigator{background:none;margin:0;padding:0}#keyFrameNavigator QToolButton{min-width:18}#keyFrameNavigator #PreviousKey{image:url('../Default/imgs/black/prevkey.svg')}#keyFrameNavigator #PreviousKey:hover{image:url('../Default/imgs/black/prevkey_over.svg')}#keyFrameNavigator #PreviousKey:disabled{image:url('../Default/imgs/black/prevkey_disabled.svg')}#keyFrameNavigator #NextKey{image:url('../Default/imgs/black/nextkey.svg')}#keyFrameNavigator #NextKey:hover{image:url('../Default/imgs/black/nextkey_over.svg')}#keyFrameNavigator #NextKey:disabled{image:url('../Default/imgs/black/nextkey_disabled.svg')}.treeview,QTreeWidget,QTreeView,#FunctionEditorTree{background-color:#949494;alternate-background-color:#8a8a8a;border:0;margin:0;outline:0}.treeview::item:selected,QTreeWidget::item:selected,QTreeView::item:selected,#FunctionEditorTree::item:selected{background-color:#225baf;color:#FFFFFF}.treeview::branch:adjoins-item,QTreeWidget::branch:adjoins-item,QTreeView::branch:adjoins-item,#FunctionEditorTree::branch:adjoins-item{border-image:url('')}.treeview::branch:has-siblings,QTreeWidget::branch:has-siblings,QTreeView::branch:has-siblings,#FunctionEditorTree::branch:has-siblings{border-image:url('')}.treeview::branch:has-siblings:adjoins-item,QTreeWidget::branch:has-siblings:adjoins-item,QTreeView::branch:has-siblings:adjoins-item,#FunctionEditorTree::branch:has-siblings:adjoins-item{border-image:url('')}.treeview::branch:has-children:closed,QTreeWidget::branch:has-children:closed,QTreeView::branch:has-children:closed,#FunctionEditorTree::branch:has-children:closed{background:url('../Default/imgs/black/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:open,QTreeWidget::branch:has-children:open,QTreeView::branch:has-children:open,#FunctionEditorTree::branch:has-children:open{background:url('../Default/imgs/black/treebranch-open.svg') no-repeat;background-position:center center;image:none}.treeview::branch:has-children:has-siblings:closed,QTreeWidget::branch:has-children:has-siblings:closed,QTreeView::branch:has-children:has-siblings:closed,#FunctionEditorTree::branch:has-children:has-siblings:closed{background:url('../Default/imgs/black/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:has-siblings:open,QTreeWidget::branch:has-children:has-siblings:open,QTreeView::branch:has-children:has-siblings:open,#FunctionEditorTree::branch:has-children:has-siblings:open{background:url('../Default/imgs/black/treebranch-open.svg') no-repeat;background-position:center center;border-image:none;image:none}QListView{outline:0;background:#949494;alternate-background-color:#8a8a8a}#TabBarContainer{background-color:#6c6c6c}.Button,QPushButton,.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{background-color:#a6a6a6;border:1 solid #525252;border-radius:2;color:#000;margin:0;padding:3 15}.Button:hover,QPushButton:hover,.ComboBox:hover,#ViewerFpsSlider::sub-line:horizontal:hover,#ViewerFpsSlider::add-line:horizontal:hover,QComboBox:hover{background-color:#bbb;border-color:#525252;color:#000}.Button:pressed,QPushButton:pressed,#ViewerFpsSlider::sub-line:horizontal:pressed,#ViewerFpsSlider::add-line:horizontal:pressed{background-color:#e1e1e1;border-color:#525252;color:#000}.Button:checked,QPushButton:checked{background-color:#5a5a5a;border-color:#454545;color:#c0c0c0}.Button:checked:hover,QPushButton:checked:hover{background-color:#5f5f5f}.Button:checked:hover:pressed,QPushButton:checked:hover:pressed{background:#5a5a5a}.Button:disabled,QPushButton:disabled,.ComboBox:disabled,#ViewerFpsSlider::sub-line:horizontal:disabled,#ViewerFpsSlider::add-line:horizontal:disabled,QComboBox:disabled{background-color:#8d8d8d;border-color:#737373;color:rgba(0,0,0,0.466)}#PushButton_NoPadding{padding:3}.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{padding:1 0 1 4;margin:1 0}.ComboBox::drop-down,QComboBox::drop-down{image:url('../Default/imgs/black/combo_downarrow.svg');image-position:center center;width:16}.ComboBox::drop-down:disabled,QComboBox::drop-down:disabled{image:url('../Default/imgs/black/combo_downarrow_disabled.svg')}.ComboBox QAbstractItemView,QComboBox QAbstractItemView{background-color:#949494;border:1 solid #404040;selection-background-color:#225baf;selection-color:#FFFFFF}.LineEdit,QLineEdit,#TaskSheetItem,#tasksRemoveBox,#tasksAddBox{background-color:#e6e6e6;border:1 solid #525252;border-radius:2;color:#000;selection-background-color:#225baf;selection-color:#FFFFFF;padding:0 0 0 1}.LineEdit:focus,QLineEdit:focus,#TaskSheetItem:focus,#tasksRemoveBox:focus,#tasksAddBox:focus{background-color:#e6e6e6;border-color:#525252;color:#000}.LineEdit:disabled,QLineEdit:disabled,#TaskSheetItem:disabled,#tasksRemoveBox:disabled,#tasksAddBox:disabled{background-color:#9a9a9a;border-color:#696969;color:rgba(0,0,0,0.466)}.CheckBox,QCheckBox{color:#000}.CheckBox:hover,QCheckBox:hover,.RadioButton:hover,QRadioButton:hover{color:#fff}.CheckBox:disabled,QCheckBox:disabled{color:rgba(0,0,0,0.466)}.CheckBox::indicator,QMenu::indicator,QCheckBox::indicator,.GroupBox::indicator,QGroupBox::indicator{background-color:#cdcdcd;border:1 solid #525252;border-radius:2;height:9;padding:1;width:9}.CheckBox::indicator:hover,QMenu::indicator:hover,.CheckBox::indicator:checked:hover,QCheckBox::indicator:hover,.GroupBox::indicator:hover,QMenu::indicator:checked:hover,QCheckBox::indicator:checked:hover,.GroupBox::indicator:checked:hover,QGroupBox::indicator:hover,QGroupBox::indicator:checked:hover{background-color:#e6e6e6;border-color:#525252}.CheckBox::indicator:checked,QMenu::indicator:checked,QCheckBox::indicator:checked,.GroupBox::indicator:checked,QGroupBox::indicator:checked{background-color:#cdcdcd;border-color:#525252;image:url('../Default/imgs/black/checkmark.svg')}.CheckBox::indicator:checked:disabled,QMenu::indicator:checked:disabled,QCheckBox::indicator:checked:disabled,.GroupBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled{background-color:#8d8d8d;border-color:#737373;image:url('../Default/imgs/black/checkmark_disabled.svg')}.CheckBox::indicator:disabled,QMenu::indicator:disabled,QCheckBox::indicator:disabled,.GroupBox::indicator:disabled,QGroupBox::indicator:disabled{background-color:#8d8d8d;border-color:#737373}.RadioButton::indicator:unchecked,QRadioButton::indicator:unchecked,#CameraSettingsRadioButton_Small::indicator:unchecked{image:url('../Default/imgs/black/radiobutton_unchecked.svg');image-position:center center}.RadioButton::indicator:checked,QRadioButton::indicator:checked,#CameraSettingsRadioButton_Small::indicator:checked{image:url('../Default/imgs/black/radiobutton_checked.svg');image-position:center center}.GroupBox,QGroupBox{margin:6 0 0 0;padding:5 0}.GroupBox::title,QGroupBox::title{subcontrol-origin:margin;left:15;margin:-3 0 0 0;padding:0 3}.GroupBox::title:hover,QGroupBox::title:hover{color:#fff}.GroupBox::title:disabled,QGroupBox::title:disabled{color:rgba(0,0,0,0.466)}.GroupBox::indicator,QGroupBox::indicator{subcontrol-origin:margin;margin-top:2}.GroupBox:disabled,QGroupBox:disabled{color:rgba(0,0,0,0.466)}.Slider::groove:horizontal,QSlider::groove:horizontal{background-color:transparent;background-image:url('../Default/imgs/black/slider-groove.svg');background-position:center center;background-repeat:repeat-x;margin:0;height:20;min-height:20}.Slider::groove:horizontal:disabled,QSlider::groove:horizontal:disabled{background-image:url('../Default/imgs/black/slider-groove_disabled.svg')}.Slider::handle:horizontal,QSlider::handle:horizontal{width:10;margin:-2 0;image:url('../Default/imgs/black/slider-handle.svg')}.Slider::handle:horizontal:disabled,QSlider::handle:horizontal:disabled{image:url('../Default/imgs/black/slider-handle_disabled.svg')}#IntPairField,#DoublePairField{qproperty-LightLineColor:#484848;qproperty-LightLineEdgeColor:#484848;qproperty-DarkLineColor:#484848;qproperty-MiddleLineColor:#484848;qproperty-HandleLeftPixmap:url("../Default/imgs/black/slider-handle.svg");qproperty-HandleRightPixmap:url("../Default/imgs/black/slider-handle.svg");qproperty-HandleLeftGrayPixmap:url("../Default/imgs/black/slider-handle_disabled.svg");qproperty-HandleRightGrayPixmap:url("../Default/imgs/black/slider-handle_disabled.svg")}#DirTreeView{background-color:#949494;alternate-background-color:#949494;border:1 solid #404040;border-right:0}DvItemViewerPanel{qproperty-TextColor:#000;qproperty-AlternateBackground:#8a8a8a;qproperty-SelectedTextColor:#FFFFFF;qproperty-FolderTextColor:#071b9b;qproperty-SelectedItemBackground:#225baf}#FileBrowser DvItemViewerPanel,#SceneCast DvItemViewerPanel{background-color:#949494}#FileBrowser #castFrame,#SceneCast #castFrame{border-top:1 solid #404040;border-right:1 solid #404040;border-bottom:1 solid #404040;margin:0}#FileBrowser QToolButton,#SceneCast QToolButton{padding:1}DvDirTreeView{qproperty-TextColor:#000;qproperty-SelectedTextColor:#FFFFFF;qproperty-SelectedItemBackground:#225baf;qproperty-FolderTextColor:#071b9b;qproperty-SelectedFolderTextColor:#FFFFFF;alternate-background-color:#8a8a8a;background-color:#949494;border:1 solid #404040}#FileDoesNotExistLabel{color:#f00}#SceneCast QToolBar{border-top:1 solid #404040}#SceneCast QToolButton{margin:3 1 2 1;padding:1}#CastBrowser{border:0;margin:0}#FilmStrip QComboBox{border-radius:0;border-width:0}#FilmStrip QComboBox QAbstractItemView{background-color:#949494}#CleanupSettings #CleanupSettingsFrame{margin-top:2;margin-bottom:4}#CleanupSettings QGroupBox{margin-bottom:3}ParamsPage{qproperty-TextColor:#000}#CameraSettingsButton{padding:2}#CameraSettingsRadioButton:hover{background:none}#CameraSettingsRadioButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#CameraSettingsRadioButton::indicator:unchecked{image:url('../Default/imgs/black/lock_off.svg')}#CameraSettingsRadioButton::indicator:checked{background-color:#C34040;border-color:#772626;image:url('../Default/imgs/black/lock_on.svg')}#CameraSettingsRadioButton::indicator:checked:hover{background-color:#d57a7a;border-color:#772626}#CameraSettingsDPI{color:#000}#CameraSettingsRadioButton_Small{padding:0}#CameraSettingsRadioButton_Small::indicator{background-color:transparent;border:0;height:21;margin:0;width:11}#ForceSquaredPixelButton{height:16;border:1 solid rgba(255,255,255,0);image:url('../Default/imgs/black/fsp_unchecked.svg');padding:2;width:16;margin:0}#ForceSquaredPixelButton:checked{image:url('../Default/imgs/black/fsp_checked.svg')}#OutputSettingsLabel{color:#000}PencilTestPopup{min-height:730px;min-width:512px}#MatchLineButton{background-color:#a6a6a6}#MatchLineButton:checked{background-color:#cdcdcd;border:2 solid #225baf;border-radius:2}#LargeSizedText{font-size:17}#StartupLabel{padding:3}#StartupLabel:hover{background:#9a9a9a}QStatusBar{background-color:#c0c0c0}QStatusBar::item{border:0}QStatusBar QLabel{background-color:#c0c0c0}QStatusBar #StatusBarLabel{background-color:#fff;padding:1 3}#TitleTxtLabel{color:#000}#StyleEditor QPushButton{margin:2 1;padding:0}#StyleEditor #TabBarContainer{margin-left:-4}#StyleEditor #bottomWidget{border-top:1 solid #404040;padding:3 2 8 3}#StyleEditor #bottomWidget QPushButton{padding:3 5}#StyleEditorTabBar::tab::first{border-left:1 solid #404040}#HexagonalColorWheel{qproperty-BGColor:#808080}#colorSlider::groove:horizontal{height:1;border-image:none}#colorSlider::handle:horizontal{width:8;margin:-8 -4}#colorSliderAddButton,#colorSliderSubButton{background:none;border-color:transparent;image-position:center center;min-height:16;padding:0;min-width:18}#colorSliderAddButton{image:url('../Default/imgs/black/scroll-right.svg')}#colorSliderSubButton{image:url('../Default/imgs/black/scroll-left.svg')}#PlainColorPageParts{border-bottom:1 solid #404040}#PlainColorPageParts QLineEdit{max-width:35}PaletteViewer DvScrollWidget QPushButton{border-top:0;margin-bottom:1;max-width:15;min-width:15}PaletteViewer DvScrollWidget #ScrollLeftButton{border-radius:0;margin-bottom:1;max-width:16;min-width:16}PaletteViewer DvScrollWidget #ScrollRightButton{border-radius:0;margin-left:1;margin-bottom:1;max-width:16;min-width:16}PaletteViewer QToolBar{background:none;border-bottom:1 solid #404040;padding:0;margin:0}PaletteViewer QToolBar::separator:horizontal{margin:0}PaletteViewer QToolBar QToolButton{margin:0 0 1 0;padding:1 0 2 0}#PageViewer{qproperty-TextColor:#000}#PaletteLockButton{border-radius:0;margin:0 0 1 1}#PaletteLockButton:checked{background-color:#C34040;border-color:#772626}#PaletteLockButton:checked:hover{background-color:#d57a7a;border-color:#772626}#WordButton{padding-right:0;padding-left:0}QDialog{background-color:#808080}QDialog #dialogButtonFrame{background-color:#767676;border-top:1 solid #404040}QDialog #dialogButtonFrame QPushButton{border-color:#525252;outline:0}QDialog #dialogButtonFrame QPushButton:focus{background-color:#B5C0D0;border-color:#485971;color:#000}QDialog #dialogButtonFrame QPushButton:focus:hover{background-color:#ced5e0}QDialog #dialogButtonFrame QPushButton:focus:pressed{background-color:#e1e1e1;border-color:#525252;color:#000}#SceneSettings QLabel{color:#000}#PreferencesPopup QListWidget{background-color:#949494;alternate-background-color:#949494;border:1 solid #404040;font-size:13}#PreferencesPopup QListWidget::item{border:0;padding:3}#PreferencesPopup QListWidget::item:hover{background-color:#9f9f9f;color:#000;background-color:#a9a9a9}#PreferencesPopup QListWidget::item:selected{background-color:#225baf;color:#FFFFFF}#ShortcutTree{border:1 solid #404040}#ShortcutTree::item{padding:1 0}#ShortcutTree QScrollBar:vertical{width:16;margin-right:-1}ProjectPopup QLabel{color:#000}#GearButton{qproperty-icon:url('../Default/imgs/black/gear.svg')}#SubfolderButton{qproperty-icon:url('../Default/imgs/black/subfolder.svg')}SchematicViewer{qproperty-TextColor:#000;qproperty-VerticalLineColor:#646464;qproperty-LevelColumnColor:#76b776;qproperty-VectorColumnColor:#c0c07a;qproperty-ChildColumnColor:#d69adb;qproperty-FullcolorColumnColor:#8bbdc1;qproperty-FxColumnColor:#82815d;qproperty-PaletteColumnColor:#2aab9a;qproperty-MeshColumnColor:#ac78d4;qproperty-TableColor:#a4a4bf;qproperty-ActiveCameraColor:#6ba5de;qproperty-OtherCameraColor:#8f9c9e;qproperty-GroupColor:#6698c6;qproperty-PegColor:#be8a56;qproperty-SplineColor:#7bb821;qproperty-ActiveOutputColor:#6ba5de;qproperty-OtherOutputColor:#8f9c9e;qproperty-XsheetColor:#a4a4bf;qproperty-NormalFxColor:#8d9caf;qproperty-MacroFxColor:#ae8ca5;qproperty-ImageAdjustFxColor:#9c9ab4;qproperty-LayerBlendingFxColor:#709ba5;qproperty-MatteFxColor:#ba8585;qproperty-SchematicPreviewButtonBgOnColor:#c8c864;qproperty-SchematicPreviewButtonOnImage:url('../Default/imgs/black/x_prev_eye_on.svg');qproperty-SchematicPreviewButtonBgOffColor:rgba(200,200,100,0.5);qproperty-SchematicPreviewButtonOffImage:url('../Default/imgs/black/x_prev_eye_off.svg');qproperty-SchematicCamstandButtonBgOnColor:#eb906b;qproperty-SchematicCamstandButtonOnImage:url('../Default/imgs/black/x_table_view_on.svg');qproperty-SchematicCamstandButtonTranspImage:url('../Default/imgs/black/x_table_view_transp.svg');qproperty-SchematicCamstandButtonBgOffColor:rgba(235,144,107,0.5);qproperty-SchematicCamstandButtonOffImage:url('../Default/imgs/black/x_table_view_off.svg')}#SchematicBottomFrame{background-color:#808080;border:0;margin:0;padding:0}#SchematicBottomFrame QToolBar::separator:horizontal{margin:0}#SchematicBottomFrame QToolBar QToolButton{padding:0;margin:2}#SchematicSceneViewer{background-color:#737373;border-bottom:1 solid #404040}#FxSettingsTabBar::tab{border-top:1 solid #404040}#FxSettingsTabBar::tab::first,#FxSettingsTabBar::tab::only-one{border-left:1 solid #404040}FxSettings QToolBar{border-top:1 solid #404040;border-right:1 solid #404040;border-left:1 solid #404040;min-height:23;padding:3 0}FxSettings QToolBar QToolBar{border:0}#FxSettingsLabel{color:#000}#FxSettingsHelpButton{background-color:#80a0dc;color:#000;padding-top:0;padding-bottom:0}#FxSettingsHelpButton:hover{background-color:#a8bee7}#ScriptConsole{font-family:'Courier New',monospace;border:0;color:#000000;padding:3}#ScriptConsole QFrame{background-color:#dcdcdc}#ScriptConsole TPanelTitleBar{background-color:#5a5a5a}#TaskSheetItemLabel{color:#000}#Tasks QToolBar{border-bottom:1 solid #404040;margin:0;padding:0}#Tasks QToolBar QToolButton{margin:2 2 3 2}#ToolBar QToolBar{padding-left:2}#ToolOptions TPanelTitleBar{border-right:1 solid #404040;border-bottom:0}#CommandBar TPanelTitleBar{border-right:1 solid #404040;border-bottom:0}IconViewField{qproperty-ThicknessPixmap:url("../Default/imgs/black/selectiontool_thickness.svg")}#EditToolLockButton{spacing:0}#EditToolLockButton:hover{background:none}#EditToolLockButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#EditToolLockButton::indicator:unchecked{image:url('../Default/imgs/black/lock_off.svg')}#EditToolLockButton::indicator:checked{background-color:#C34040;border-color:#772626;image:url('../Default/imgs/black/lock_on.svg')}#EditToolLockButton::indicator:checked:hover{background-color:#d57a7a;border-color:#772626}PopupButton::menu-indicator{border-left:0;height:17;image:url('../Default/imgs/black/combo_downarrow.svg');width:10}PopupButton::menu-indicator:hover{image:url('../Default/imgs/black/combo_downarrow.svg')}PopupButton::menu-indicator:disabled{image:url('../Default/imgs/black/combo_downarrow_disabled.svg')}#Cap,#Join{padding:0 4 0 -8;max-width:32;min-width:32}#Cap QMenu,#Join QMenu{max-width:28;min-width:28}#Cap QMenu::item,#Join QMenu::item{max-width:28;min-width:28;padding:0}QToolBar#MediumPaddingToolBar QToolButton{padding-left:3;padding-right:3}QToolBar#WidePaddingToolBar QToolButton{padding-left:6;padding-right:6}#CommandBar{margin:0;padding:0;border:0}#CommandBar::separator:horizontal{margin-right:3;margin-left:3}#expandButton:checked{background-color:transparent;border-color:transparent;color:#000}#expandButton:checked:hover{background-color:#bbb;border-color:#525252}#expandButton:checked:pressed{background-color:#e1e1e1;border-color:#525252}#ComboViewerPanel Toolbar{border-bottom:1 solid #404040}#ComboViewerPanel Toolbar::separator:horizontal{margin:0 0 0 2}#ComboViewerPanel Toolbar QToolButton{margin:2 0 3 2}#ComboViewerToolOptions{border-bottom:1 solid #404040}#ComboViewer #ToolBarContainer,#ViewerPanel #ToolBarContainer,FlipBook #ToolBarContainer{background-color:transparent;border-top:2 solid #404040;border-bottom:1 solid #404040;padding-right:-1}#flipCustomize{margin-left:3}#flipCustomize::menu-button{background-color:transparent;width:35}#flipCustomize::menu-arrow{image:none}QToolBar#FlipConsolePlayToolBar::separator:horizontal{margin:0 3}QToolBar#FlipConsolePlayToolBar QToolButton{margin-top:2;margin-bottom:2;height:16;padding-left:1;padding-right:1}#ViewerFpsSlider{background-color:transparent;background-image:url('../Default/imgs/black/slider-groove.svg');background-position:center center;background-repeat:repeat-x;border:0;height:19;margin:0 3 0 37;max-width:300;min-width:0}#ViewerFpsSlider::sub-line:horizontal{subcontrol-origin:absolute;background-color:#a6a6a6;border:1 solid #525252;border-top-left-radius:2;border-bottom-left-radius:2;height:16;left:-33;width:14}#ViewerFpsSlider::add-line:horizontal{subcontrol-position:left;background-color:#a6a6a6;border:1 solid #525252;border-top-right-radius:2;border-bottom-right-radius:2;left:18;height:16;image-position:center center;width:13}#ViewerFpsSlider::handle::horizontal{background-color:#a6a6a6;border:1 solid #404040;border-radius:2;margin:2 0 3 0;min-width:9;width:9;max-width:9}FlipSlider{qproperty-PBHeight:15;qproperty-PBOverlay:url('../Default/imgs/black/flipslider.svg');qproperty-PBColorMarginLeft:1;qproperty-PBColorMarginTop:2;qproperty-PBColorMarginRight:1;qproperty-PBColorMarginBottom:2;qproperty-PBMarker:url('../Default/imgs/black/flipmarker.svg');qproperty-PBMarkerMarginLeft:3;qproperty-PBMarkerMarginRight:3;qproperty-notStartedColor:#8b2525;qproperty-startedColor:#00a808;qproperty-baseColor:#676767;qproperty-finishedColor:#676767}Ruler{qproperty-ParentBGColor:#c0c0c0;qproperty-ScaleColor:#000}#RulerToolOptionValues{color:#000}#xsheetArea,#ScrollArea{background-color:#6c6c6c;border:0}#xsheetScrollArea{border:0}#cornerWidget QToolButton{padding:0}#xsheetColumnAreaMenu_Preview{background-color:#E6E678}#xsheetColumnAreaMenu_Lock{background-color:#F5F5F5}#xsheetColumnAreaMenu_Camstand{background-color:#FFA480}#xsheetColumnAreaMenu_Preview,#xsheetColumnAreaMenu_Lock,#xsheetColumnAreaMenu_Camstand{color:#000}#noteTextEdit{color:#000}XsheetViewer{qproperty-TextColor:#000;qproperty-BGColor:#929292;qproperty-LightLineColor:#616161;qproperty-MarkerLineColor:#000;qproperty-VerticalLineColor:#646464;qproperty-VerticalLineHeadColor:#393939;qproperty-PreviewFrameTextColor:#000eb6;qproperty-CurrentRowBgColor:#B5C0D0;qproperty-EmptyColumnHeadColor:#808080;qproperty-SelectedColumnTextColor:#9e0000;qproperty-EmptyCellColor:#7c7c7c;qproperty-NotEmptyColumnColor:#8a8a8a;qproperty-SelectedEmptyCellColor:#b3b3b3;qproperty-LevelColumnColor:#76b776;qproperty-LevelColumnBorderColor:#496549;qproperty-SelectedLevelColumnColor:#9bc59b;qproperty-VectorColumnColor:#c0c07a;qproperty-VectorColumnBorderColor:#71714a;qproperty-SelectedVectorColumnColor:#cdcda0;qproperty-ChildColumnColor:#d69adb;qproperty-ChildColumnBorderColor:#9c53a3;qproperty-SelectedChildColumnColor:#e3c2e6;qproperty-FullcolorColumnColor:#8bbdc1;qproperty-FullcolorColumnBorderColor:#577476;qproperty-SelectedFullcolorColumnColor:#afcdd0;qproperty-FxColumnColor:#82815d;qproperty-FxColumnBorderColor:#404039;qproperty-SelectedFxColumnColor:#97967b;qproperty-ReferenceColumnColor:#ababab;qproperty-ReferenceColumnBorderColor:#6b6b6b;qproperty-SelectedReferenceColumnColor:#c4c4c4;qproperty-PaletteColumnColor:#2aab9a;qproperty-PaletteColumnBorderColor:#173e39;qproperty-SelectedPaletteColumnColor:#40c8b6;qproperty-MeshColumnColor:#ac78d4;qproperty-MeshColumnBorderColor:#6b418c;qproperty-SelectedMeshColumnColor:#c3a2dd;qproperty-SoundTextColumnColor:#c8c8c8;qproperty-SoundTextColumnBorderColor:#8c8c8c;qproperty-SelectedSoundTextColumnColor:#e2e2e2;qproperty-SoundColumnColor:#acba82;qproperty-SoundColumnBorderColor:#656b51;qproperty-SelectedSoundColumnColor:#c0c9a6;qproperty-SoundColumnHlColor:#f5ffe6;qproperty-SoundColumnTrackColor:#5a642d;qproperty-ColumnHeadPastelizer:#fff;qproperty-SelectedColumnHead:#bed2f0;qproperty-LightLightBGColor:#808080;qproperty-LightBGColor:#f0f0f0;qproperty-DarkBGColor:#e1e1e1;qproperty-DarkLineColor:#969696;qproperty-XsheetColumnNameBgColor:rgba(0,0,0,0);qproperty-XsheetDragBarHighlightColor:rgba(255,255,255,0.5);qproperty-XsheetPreviewButtonBgOnColor:#c8c864;qproperty-XsheetPreviewButtonOnImage:url('../Default/imgs/black/x_prev_eye_on.svg');qproperty-XsheetPreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetPreviewButtonOffImage:url('../Default/imgs/black/x_prev_eye_off.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');qproperty-XsheetCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetCamstandButtonOffImage:url('../Default/imgs/black/x_table_view_off.svg');qproperty-XsheetLockButtonBgOnColor:rgba(255,255,255,0.3);qproperty-XsheetLockButtonOnImage:url('../Default/imgs/black/x_lock_on.svg');qproperty-XsheetLockButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetLockButtonOffImage:url('../Default/imgs/black/x_lock_off.svg');qproperty-XsheetConfigButtonBgColor:rgba(255,255,255,0);qproperty-XsheetConfigButtonImage:url('../Default/imgs/black/x_config.svg');qproperty-TimelinePreviewButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOnImage:url('../Default/imgs/black/timeline_toggle_on.svg');qproperty-TimelinePreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOffImage:url('../Default/imgs/black/timeline_toggle_off.svg');qproperty-TimelineCamstandButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOnImage:url('../Default/imgs/black/timeline_toggle_on.svg');qproperty-TimelineCamstandButtonTranspImage:url('../Default/imgs/black/timeline_toggle_transp.svg');qproperty-TimelineCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOffImage:url('../Default/imgs/black/timeline_toggle_off.svg');qproperty-TimelineLockButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOnImage:url('../Default/imgs/black/timeline_toggle_on.svg');qproperty-TimelineLockButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOffImage:url('../Default/imgs/black/timeline_toggle_off.svg');qproperty-TimelineConfigButtonBgColor:rgba(255,255,255,0);qproperty-TimelineConfigButtonImage:url('../Default/imgs/black/timeline_config.svg');qproperty-LayerHeaderPreviewImage:url('../Default/imgs/black/layer_header_prev_eye.svg');qproperty-LayerHeaderPreviewOverImage:url('../Default/imgs/black/layer_header_prev_eye_over.svg');qproperty-LayerHeaderCamstandImage:url('../Default/imgs/black/layer_header_table_view.svg');qproperty-LayerHeaderCamstandOverImage:url('../Default/imgs/black/layer_header_table_view_over.svg');qproperty-LayerHeaderLockImage:url('../Default/imgs/black/lock_on.svg');qproperty-LayerHeaderLockOverImage:url('../Default/imgs/black/lock_on_over.svg')}#XSheetToolbar{margin:0;padding:0;border:0}#XSheetToolbar QToolButton{padding:0;margin:4 1;min-height:19;height:19}#XSheetToolbar::separator:horizontal{margin:0 4}#FunctionEditor QToolBar{border-bottom:1 solid #404040}#FunctionEditor QToolBar QToolBar{border:0}#FunctionEditor QToolBar QLabel{margin-left:5}#FunctionEditor QToolBar QToolButton{height:18}#FunctionEditorTree{border-top:1 solid #404040}FunctionTreeView{qproperty-TextColor:#000;qproperty-CurrentTextColor:#a70000}FunctionPanel{qproperty-BGColor:#5a5a5a;qproperty-ValueLineColor:#4d4d4d;qproperty-FrameLineColor:#4d4d4d;qproperty-OtherCurvesColor:#c5c5c5;qproperty-RulerBackground:#676767;qproperty-TextColor:#000;qproperty-SubColor:#fff;qproperty-SelectedColor:#fcae06}SpreadsheetViewer{qproperty-LightLightBGColor:#808080;qproperty-CurrentRowBgColor:#B5C0D0;qproperty-LightLineColor:#616161;qproperty-MarkerLineColor:#000;qproperty-BGColor:#8a8a8a;qproperty-VerticalLineColor:#646464;qproperty-KeyFrameColor:#db8b36;qproperty-KeyFrameBorderColor:#7b4a16;qproperty-SelectedKeyFrameColor:#dea466;qproperty-InBetweenColor:#c2c2b0;qproperty-InBetweenBorderColor:#636356;qproperty-SelectedInBetweenColor:#d6d6cf;qproperty-SelectedEmptyColor:#b3b3b3;qproperty-SelectedSceneRangeEmptyColor:#d2d2d2;qproperty-TextColor:#000;qproperty-ColumnHeaderBorderColor:#393939;qproperty-SelectedColumnTextColor:#9e0000}#ExpressionField{background-color:#fff;border:1 solid #6b6b6b;margin:0}#FunctionSegmentViewerLinkButton{background-image:url('../Default/imgs/black/segment_unlinked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:hover{background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:checked{background-image:url('../Default/imgs/black/segment_linked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:disabled{background-image:url('../Default/imgs/black/segment_disabled.svg');background-repeat:no-repeat} \ No newline at end of file +.button-show,#LoadLevelShowButton,#CleanupSettingsShowButton,#OutputSettingsShowButton,#FxSettingsPreviewShowButton{image:url('../Default/imgs/black/plus.svg');image-position:center center;margin:0;padding:1;min-width:10;min-height:10}.button-show:checked,#LoadLevelShowButton:checked,#CleanupSettingsShowButton:checked,#OutputSettingsShowButton:checked,#FxSettingsPreviewShowButton:checked{background-color:#5a5a5a;border-color:#454545;image:url('../Default/imgs/black/minus.svg')}.button-show:checked:pressed,#LoadLevelShowButton:checked:pressed,#CleanupSettingsShowButton:checked:pressed,#OutputSettingsShowButton:checked:pressed,#FxSettingsPreviewShowButton:checked:pressed{background-color:#e1e1e1;border-color:#525252}.button-show:checked:hover,#LoadLevelShowButton:checked:hover,#CleanupSettingsShowButton:checked:hover,#OutputSettingsShowButton:checked:hover,#FxSettingsPreviewShowButton:checked:hover{background-color:#5f5f5f}.button-tool,QToolButton,#CameraSettingsRadioButton::indicator,#ForceSquaredPixelButton,#SchematicBottomFrame QToolBar QToolButton,#EditToolLockButton::indicator,#flipCustomize{background-color:rgba(255,255,255,0);border:1 solid rgba(255,255,255,0);border-radius:2;color:#000;margin:1;padding:0}.button-tool:hover,QToolButton:hover,#CameraSettingsRadioButton::indicator:hover,#ForceSquaredPixelButton:hover,#colorSliderAddButton:hover,#colorSliderSubButton:hover,#SchematicBottomFrame QToolBar QToolButton:hover,#EditToolLockButton::indicator:hover,#flipCustomize:hover{background-color:#bbb;border-color:#525252;color:#000}.button-tool:pressed,QToolButton:pressed,#CameraSettingsRadioButton::indicator:pressed,#ForceSquaredPixelButton:pressed,#colorSliderAddButton:pressed,#colorSliderSubButton:pressed,#SchematicBottomFrame QToolBar QToolButton:pressed,#EditToolLockButton::indicator:pressed,#flipCustomize:pressed{background-color:#e1e1e1;border-color:#525252;color:#000}.button-tool:checked,QToolButton:checked,#CameraSettingsRadioButton::indicator:checked,#ForceSquaredPixelButton:checked,#SchematicBottomFrame QToolBar QToolButton:checked,#EditToolLockButton::indicator:checked,#flipCustomize:checked{background-color:#5a5a5a;border-color:#454545;color:#c0c0c0}.button-tool:checked:hover,QToolButton:checked:hover,#CameraSettingsRadioButton::indicator:checked:hover,#ForceSquaredPixelButton:checked:hover,#SchematicBottomFrame QToolBar QToolButton:checked:hover,#EditToolLockButton::indicator:checked:hover,#flipCustomize:checked:hover{background-color:#6e6e6e;border-color:#454545}.button-tool:disabled,QToolButton:disabled,#CameraSettingsRadioButton::indicator:disabled,#ForceSquaredPixelButton:disabled,#SchematicBottomFrame QToolBar QToolButton:disabled,#EditToolLockButton::indicator:disabled,#flipCustomize:disabled{color:rgba(0,0,0,0.466)}.button-flat,PaletteViewer QToolBar QToolButton{background-color:none;border:0;border-radius:0;margin:0}.button-flat:hover,PaletteViewer QToolBar QToolButton:hover{background-color:#bbb}.button-flat:pressed,PaletteViewer QToolBar QToolButton:pressed{background-color:#404040}.frame,.GroupBox,#LoadLevelFrame,#PsdSettingsGroupBox,#CleanupSettingsFrame,#OutputSettingsBox,#OutputSettingsCameraBox,#SolidLineFrame,#FunctionParametersPanel,QGroupBox{border:1 solid #404040;border-radius:2}.tab-container,#TabBarContainer{background-color:transparent;qproperty-BottomAboveLineColor:#6c6c6c;qproperty-BottomBelowLineColor:#404040}.tab-flat,#StyleEditorTabBar::tab,#PaletteTabBar::tab,#FxSettingsTabBar::tab{background-color:#5a5a5a;border-right:1 solid #404040;border-bottom:1 solid #404040;color:#c0c0c0;padding:3 4 3 4}.tab-flat:hover,#StyleEditorTabBar::tab:hover,#PaletteTabBar::tab:hover,#FxSettingsTabBar::tab:hover{background-color:#6e6e6e;color:#fff}.tab-flat:selected,#StyleEditorTabBar::tab:selected,#PaletteTabBar::tab:selected,#FxSettingsTabBar::tab:selected{background-color:#808080;color:#000;border-bottom-color:#808080}.tab-flat:only-one,#StyleEditorTabBar::tab:only-one,#PaletteTabBar::tab:only-one,#FxSettingsTabBar::tab:only-one{margin:0}.tab-round{background-color:#5a5a5a;border-top:1 solid #404040;border-right:1 solid #404040;border-left:1 solid #404040;border-bottom:1 solid #404040;color:#c0c0c0;margin:3 -1 0 0;padding:2 7 1 7}.tab-round:hover{background-color:#6e6e6e;color:#fff}.tab-round:selected{background-color:#808080;border-top-right-radius:2;border-top-left-radius:2;border-bottom-color:#808080;color:#000;margin:1 -1 -1 0;padding:2 7 2 7}.tab-round:only-one{margin:1 0 0 0;padding:3 7 3 7}.tab-round:last{margin-right:0;border-top-right-radius:2}.tab-round:first{border-top-left-radius:2}QWidget{background-color:#808080;color:#000}QWidget:disabled{color:rgba(0,0,0,0.466)}QFrame{border:0;margin:0;padding:0}QToolTip,#helpToolTip{background-color:#fff;border:1 solid #000;color:#000;padding:1 1}#DockSeparator,QMainWindow::separator,QSplitter::handle{background-color:#272727;height:4;width:4}#TDockPlaceholder{background-color:#F77272}TPanel{background-color:#272727}#TopBar{background:#808080;border:0;border-bottom:1 solid #404040;height:21}#TopBar #EditToolLockButton{background:#808080;spacing:0}#TopBar #EditToolLockButton::indicator{background:none;border:none;height:18;margin:1 2 0 0;padding-left:0;padding-right:0}#TopBarTabContainer{background-color:#808080;margin-bottom:1}#StackedMenuBar{border:0;margin:0;padding:0}QMenuBar{background-color:#808080;border:0}QMenuBar::item{background-color:#808080;border-left:1 solid #808080;margin:0;padding:3 5}QMenuBar::item:selected{background-color:#9f9f9f;color:#000}QMenuBar::item:pressed{background-color:#225baf;color:#FFFFFF}#TopBarTab{margin:0;padding:0}#TopBarTab::tab{background-color:#5a5a5a;border-top:1 solid #404040;border-right:1 solid #404040;color:#afafaf;margin:0 0 0 0;padding:2 8 3 8}#TopBarTab::tab:hover{background-color:#6e6e6e;color:#fff}#TopBarTab::tab:selected{background-color:#9a9a9a;color:#000}#TopBarTab::tab:first{border-left:1 solid #404040}#TopBarTab::tab:last{border-right:1 solid #404040}QMenu{background-color:#949494;border:1 solid #404040;padding:2 0}QMenu::item{padding:3 28}QMenu::item:selected{background-color:#225baf;color:#FFFFFF}QMenu::item:checked{color:#000}QMenu::item:checked:selected{background-color:#225baf;color:#FFFFFF}QMenu::item:disabled{background:none;color:rgba(0,0,0,0.466)}QMenu::item:disabled:selected{border-color:transparent}QMenu::separator{border-top:1 solid #6e6e6e;height:0;margin:2 0}QMenu::icon{border-radius:2;margin:0 0 0 3;padding:1}QMenu::icon:checked{background-color:#225baf}QMenu::indicator{margin-left:7}TPanelTitleBar{background-color:#5a5a5a;border-color:#404040;border-style:solid;border-width:0 0 1 0;height:20;min-height:20;qproperty-TitleColor:#c0c0c0;qproperty-ActiveTitleColor:#fff;qproperty-BorderPixmap:url('none');qproperty-ActiveBorderPixmap:url('../Default/imgs/black/none');qproperty-FloatBorderPixmap:url('none');qproperty-FloatActiveBorderPixmap:url('../Default/imgs/black/none')}QAbstractScrollArea::corner{background-color:#6e6e6e}QScrollBar{background-color:#6e6e6e;border:0}QScrollBar:horizontal{height:16;margin:0}QScrollBar:vertical{margin:0;width:16}QScrollBar::handle{border:1 solid #555;border-radius:2}QScrollBar::handle:horizontal:hover,QScrollBar::handle:vertical:hover{background-color:#b3b3b3;border-color:#404040}QScrollBar::handle:horizontal:pressed,QScrollBar::handle:vertical:pressed{background-color:#c7c7c7;border-color:#404040}QScrollBar::handle:horizontal{background-color:#9f9f9f;margin:2 16;min-width:20}QScrollBar::handle:vertical{background-color:#9f9f9f;margin:16 2;min-height:20}QScrollBar::add-line{subcontrol-origin:margin;border:0}QScrollBar::add-line:horizontal{subcontrol-position:right;background-color:#6e6e6e;margin:0;width:16}QScrollBar::add-line:vertical{subcontrol-position:bottom;background-color:#6e6e6e;margin:0;height:16}QScrollBar::sub-line{border:0;subcontrol-origin:margin}QScrollBar::sub-line:horizontal{subcontrol-position:left;background-color:#6e6e6e;margin:0;width:16}QScrollBar::sub-line:vertical{subcontrol-position:top;background-color:#6e6e6e;margin:0;height:16}QScrollBar::up-arrow:vertical{image:url('../Default/imgs/black/scroll-up.svg');image-position:center center}QScrollBar::up-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::down-arrow:vertical{image:url('../Default/imgs/black/scroll-down.svg');image-position:center center}QScrollBar::down-arrow:vertical:pressed{margin:1 0 0 0}QScrollBar::left-arrow:horizontal{image:url('../Default/imgs/black/scroll-left.svg');image-position:center center}QScrollBar::left-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::right-arrow:horizontal{image:url('../Default/imgs/black/scroll-right.svg');image-position:center center}QScrollBar::right-arrow:horizontal:pressed{margin:1 0 0 0}QScrollBar::sub-page:horizontal,QScrollBar::add-page:horizontal,QScrollBar::sub-page:vertical,QScrollBar::add-page:vertical{background:none}QToolBar{padding:0}QToolBar::separator:horizontal{border-left:1 solid #404040;margin:0 1;width:0}QToolBar::separator:vertical{border-top:1 solid #404040;height:0;margin:1 0}QToolBar QLabel{margin-top:1}QToolBar QToolBar{border:0}QToolButton::menu-indicator{image:none}QToolButton::menu-button{border-image:none}.DvScrollWidget QPushButton,DvScrollWidget QPushButton,#ScrollLeftButton QPushButton,#ScrollRightButton QPushButton,#ScrollUpButton QPushButton,#ScrollDownButton QPushButton{background-color:#a6a6a6;border:0 solid red;border-radius:0;padding:0;max-width:16}.DvScrollWidget QPushButton:hover,DvScrollWidget QPushButton:hover,#ScrollLeftButton QPushButton:hover,#ScrollRightButton QPushButton:hover,#ScrollUpButton QPushButton:hover,#ScrollDownButton QPushButton:hover{background-color:#bbb}.DvScrollWidget QPushButton:pressed,DvScrollWidget QPushButton:pressed,#ScrollLeftButton QPushButton:pressed,#ScrollRightButton QPushButton:pressed,#ScrollUpButton QPushButton:pressed,#ScrollDownButton QPushButton:pressed{background-color:#e1e1e1}#ScrollLeftButton,#ScrollRightButton,#ScrollUpButton,#ScrollDownButton{margin:0;min-width:16}#ScrollLeftButton{border-right:1 solid #404040;image:url('../Default/imgs/black/scroll-left.svg')}#ScrollRightButton{border-left:1 solid #404040;margin-left:3;image:url('../Default/imgs/black/scroll-right.svg')}#ScrollUpButton{image:url('../Default/imgs/black/scroll-up.svg')}#ScrollDownButton{image:url('../Default/imgs/black/scroll-down.svg')}#keyFrameNavigator{background:none;margin:0;padding:0}#keyFrameNavigator QToolButton{min-width:18}#keyFrameNavigator #PreviousKey{image:url('../Default/imgs/black/prevkey.svg')}#keyFrameNavigator #PreviousKey:hover{image:url('../Default/imgs/black/prevkey_over.svg')}#keyFrameNavigator #PreviousKey:disabled{image:url('../Default/imgs/black/prevkey_disabled.svg')}#keyFrameNavigator #NextKey{image:url('../Default/imgs/black/nextkey.svg')}#keyFrameNavigator #NextKey:hover{image:url('../Default/imgs/black/nextkey_over.svg')}#keyFrameNavigator #NextKey:disabled{image:url('../Default/imgs/black/nextkey_disabled.svg')}.treeview,QTreeWidget,QTreeView,#FunctionEditorTree{background-color:#949494;alternate-background-color:#8a8a8a;border:0;margin:0;outline:0}.treeview::item:selected,QTreeWidget::item:selected,QTreeView::item:selected,#FunctionEditorTree::item:selected{background-color:#225baf;color:#FFFFFF}.treeview::branch:adjoins-item,QTreeWidget::branch:adjoins-item,QTreeView::branch:adjoins-item,#FunctionEditorTree::branch:adjoins-item{border-image:url('')}.treeview::branch:has-siblings,QTreeWidget::branch:has-siblings,QTreeView::branch:has-siblings,#FunctionEditorTree::branch:has-siblings{border-image:url('')}.treeview::branch:has-siblings:adjoins-item,QTreeWidget::branch:has-siblings:adjoins-item,QTreeView::branch:has-siblings:adjoins-item,#FunctionEditorTree::branch:has-siblings:adjoins-item{border-image:url('')}.treeview::branch:has-children:closed,QTreeWidget::branch:has-children:closed,QTreeView::branch:has-children:closed,#FunctionEditorTree::branch:has-children:closed{background:url('../Default/imgs/black/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:open,QTreeWidget::branch:has-children:open,QTreeView::branch:has-children:open,#FunctionEditorTree::branch:has-children:open{background:url('../Default/imgs/black/treebranch-open.svg') no-repeat;background-position:center center;image:none}.treeview::branch:has-children:has-siblings:closed,QTreeWidget::branch:has-children:has-siblings:closed,QTreeView::branch:has-children:has-siblings:closed,#FunctionEditorTree::branch:has-children:has-siblings:closed{background:url('../Default/imgs/black/treebranch-closed.svg') no-repeat;background-position:center center;border-image:none;image:none}.treeview::branch:has-children:has-siblings:open,QTreeWidget::branch:has-children:has-siblings:open,QTreeView::branch:has-children:has-siblings:open,#FunctionEditorTree::branch:has-children:has-siblings:open{background:url('../Default/imgs/black/treebranch-open.svg') no-repeat;background-position:center center;border-image:none;image:none}QListView{outline:0;background:#949494;alternate-background-color:#8a8a8a}#TabBarContainer{background-color:#6c6c6c}.Button,QPushButton,.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{background-color:#a6a6a6;border:1 solid #525252;border-radius:2;color:#000;margin:0;padding:3 15}.Button:hover,QPushButton:hover,.ComboBox:hover,#ViewerFpsSlider::sub-line:horizontal:hover,#ViewerFpsSlider::add-line:horizontal:hover,QComboBox:hover{background-color:#bbb;border-color:#525252;color:#000}.Button:pressed,QPushButton:pressed,#ViewerFpsSlider::sub-line:horizontal:pressed,#ViewerFpsSlider::add-line:horizontal:pressed{background-color:#e1e1e1;border-color:#525252;color:#000}.Button:checked,QPushButton:checked{background-color:#5a5a5a;border-color:#454545;color:#c0c0c0}.Button:checked:hover,QPushButton:checked:hover{background-color:#5f5f5f}.Button:checked:hover:pressed,QPushButton:checked:hover:pressed{background:#5a5a5a}.Button:disabled,QPushButton:disabled,.ComboBox:disabled,#ViewerFpsSlider::sub-line:horizontal:disabled,#ViewerFpsSlider::add-line:horizontal:disabled,QComboBox:disabled{background-color:#8d8d8d;border-color:#737373;color:rgba(0,0,0,0.466)}#PushButton_NoPadding{padding:3}.ComboBox,.ComboBox:checked,QComboBox,QComboBox:checked{padding:1 0 1 4;margin:1 0}.ComboBox::drop-down,QComboBox::drop-down{image:url('../Default/imgs/black/combo_downarrow.svg');image-position:center center;width:16}.ComboBox::drop-down:disabled,QComboBox::drop-down:disabled{image:url('../Default/imgs/black/combo_downarrow_disabled.svg')}.ComboBox QAbstractItemView,QComboBox QAbstractItemView{background-color:#949494;border:1 solid #404040;selection-background-color:#225baf;selection-color:#FFFFFF}.LineEdit,QLineEdit,#TaskSheetItem,#tasksRemoveBox,#tasksAddBox{background-color:#e6e6e6;border:1 solid #525252;border-radius:2;color:#000;selection-background-color:#225baf;selection-color:#FFFFFF;padding:0 0 0 1}.LineEdit:focus,QLineEdit:focus,#TaskSheetItem:focus,#tasksRemoveBox:focus,#tasksAddBox:focus{background-color:#e6e6e6;border-color:#525252;color:#000}.LineEdit:disabled,QLineEdit:disabled,#TaskSheetItem:disabled,#tasksRemoveBox:disabled,#tasksAddBox:disabled{background-color:#9a9a9a;border-color:#696969;color:rgba(0,0,0,0.466)}.CheckBox,QCheckBox{color:#000}.CheckBox:hover,QCheckBox:hover,.RadioButton:hover,QRadioButton:hover{color:#fff}.CheckBox:disabled,QCheckBox:disabled{color:rgba(0,0,0,0.466)}.CheckBox::indicator,QMenu::indicator,QCheckBox::indicator,.GroupBox::indicator,QGroupBox::indicator{background-color:#cdcdcd;border:1 solid #525252;border-radius:2;height:9;padding:1;width:9}.CheckBox::indicator:hover,QMenu::indicator:hover,.CheckBox::indicator:checked:hover,QCheckBox::indicator:hover,.GroupBox::indicator:hover,QMenu::indicator:checked:hover,QCheckBox::indicator:checked:hover,.GroupBox::indicator:checked:hover,QGroupBox::indicator:hover,QGroupBox::indicator:checked:hover{background-color:#e6e6e6;border-color:#525252}.CheckBox::indicator:checked,QMenu::indicator:checked,QCheckBox::indicator:checked,.GroupBox::indicator:checked,QGroupBox::indicator:checked{background-color:#cdcdcd;border-color:#525252;image:url('../Default/imgs/black/checkmark.svg')}.CheckBox::indicator:checked:disabled,QMenu::indicator:checked:disabled,QCheckBox::indicator:checked:disabled,.GroupBox::indicator:checked:disabled,QGroupBox::indicator:checked:disabled{background-color:#8d8d8d;border-color:#737373;image:url('../Default/imgs/black/checkmark_disabled.svg')}.CheckBox::indicator:disabled,QMenu::indicator:disabled,QCheckBox::indicator:disabled,.GroupBox::indicator:disabled,QGroupBox::indicator:disabled{background-color:#8d8d8d;border-color:#737373}.RadioButton::indicator:unchecked,QRadioButton::indicator:unchecked,#CameraSettingsRadioButton_Small::indicator:unchecked{image:url('../Default/imgs/black/radiobutton_unchecked.svg');image-position:center center}.RadioButton::indicator:checked,QRadioButton::indicator:checked,#CameraSettingsRadioButton_Small::indicator:checked{image:url('../Default/imgs/black/radiobutton_checked.svg');image-position:center center}.GroupBox,QGroupBox{margin:6 0 0 0;padding:5 0}.GroupBox::title,QGroupBox::title{subcontrol-origin:margin;left:15;margin:-3 0 0 0;padding:0 3}.GroupBox::title:hover,QGroupBox::title:hover{color:#fff}.GroupBox::title:disabled,QGroupBox::title:disabled{color:rgba(0,0,0,0.466)}.GroupBox::indicator,QGroupBox::indicator{subcontrol-origin:margin;margin-top:2}.GroupBox:disabled,QGroupBox:disabled{color:rgba(0,0,0,0.466)}.Slider::groove:horizontal,QSlider::groove:horizontal{background-color:transparent;background-image:url('../Default/imgs/black/slider-groove.svg');background-position:center center;background-repeat:repeat-x;margin:0;height:20;min-height:20}.Slider::groove:horizontal:disabled,QSlider::groove:horizontal:disabled{background-image:url('../Default/imgs/black/slider-groove_disabled.svg')}.Slider::handle:horizontal,QSlider::handle:horizontal{width:10;margin:-2 0;image:url('../Default/imgs/black/slider-handle.svg')}.Slider::handle:horizontal:disabled,QSlider::handle:horizontal:disabled{image:url('../Default/imgs/black/slider-handle_disabled.svg')}#IntPairField,#DoublePairField{qproperty-LightLineColor:#484848;qproperty-LightLineEdgeColor:#484848;qproperty-DarkLineColor:#484848;qproperty-MiddleLineColor:#484848;qproperty-HandleLeftPixmap:url("../Default/imgs/black/slider-handle.svg");qproperty-HandleRightPixmap:url("../Default/imgs/black/slider-handle.svg");qproperty-HandleLeftGrayPixmap:url("../Default/imgs/black/slider-handle_disabled.svg");qproperty-HandleRightGrayPixmap:url("../Default/imgs/black/slider-handle_disabled.svg")}#DirTreeView{background-color:#949494;alternate-background-color:#949494;border:1 solid #404040;border-right:0}DvItemViewerPanel{qproperty-TextColor:#000;qproperty-AlternateBackground:#8a8a8a;qproperty-SelectedTextColor:#FFFFFF;qproperty-FolderTextColor:#071b9b;qproperty-SelectedItemBackground:#225baf}#FileBrowser DvItemViewerPanel,#SceneCast DvItemViewerPanel{background-color:#949494}#FileBrowser #castFrame,#SceneCast #castFrame{border-top:1 solid #404040;border-right:1 solid #404040;border-bottom:1 solid #404040;margin:0}#FileBrowser QToolButton,#SceneCast QToolButton{padding:1}DvDirTreeView{qproperty-TextColor:#000;qproperty-SelectedTextColor:#FFFFFF;qproperty-SelectedItemBackground:#225baf;qproperty-FolderTextColor:#071b9b;qproperty-SelectedFolderTextColor:#FFFFFF;alternate-background-color:#8a8a8a;background-color:#949494;border:1 solid #404040}#FileDoesNotExistLabel{color:#f00}#SceneCast QToolBar{border-top:1 solid #404040}#SceneCast QToolButton{margin:3 1 2 1;padding:1}#CastBrowser{border:0;margin:0}#FilmStrip QComboBox{border-radius:0;border-width:0}#FilmStrip QComboBox QAbstractItemView{background-color:#949494}#CleanupSettings #CleanupSettingsFrame{margin-top:2;margin-bottom:4}#CleanupSettings QGroupBox{margin-bottom:3}ParamsPage{qproperty-TextColor:#000}#CameraSettingsButton{padding:2}#CameraSettingsRadioButton:hover{background:none}#CameraSettingsRadioButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#CameraSettingsRadioButton::indicator:unchecked{image:url('../Default/imgs/black/lock_off.svg')}#CameraSettingsRadioButton::indicator:checked{background-color:#C34040;border-color:#772626;image:url('../Default/imgs/black/lock_on.svg')}#CameraSettingsRadioButton::indicator:checked:hover{background-color:#d57a7a;border-color:#772626}#CameraSettingsDPI{color:#000}#CameraSettingsRadioButton_Small{padding:0}#CameraSettingsRadioButton_Small::indicator{background-color:transparent;border:0;height:21;margin:0;width:11}#ForceSquaredPixelButton{height:16;border:1 solid rgba(255,255,255,0);image:url('../Default/imgs/black/fsp_unchecked.svg');padding:2;width:16;margin:0}#ForceSquaredPixelButton:checked{image:url('../Default/imgs/black/fsp_checked.svg')}#OutputSettingsLabel{color:#000}PencilTestPopup{min-height:730px;min-width:512px}#MatchLineButton{background-color:#a6a6a6}#MatchLineButton:checked{background-color:#cdcdcd;border:2 solid #225baf;border-radius:2}#LargeSizedText{font-size:17}#StartupLabel{padding:3}#StartupLabel:hover{background:#9a9a9a}QStatusBar{background-color:#c0c0c0}QStatusBar::item{border:0}QStatusBar QLabel{background-color:#c0c0c0}QStatusBar #StatusBarLabel{background-color:#fff;padding:1 3}#TitleTxtLabel{color:#000}#StyleEditor QPushButton{margin:2 1;padding:0}#StyleEditor #TabBarContainer{margin-left:-4}#StyleEditor #bottomWidget{border-top:1 solid #404040;padding:3 2 8 3}#StyleEditor #bottomWidget QPushButton{padding:3 5}#StyleEditorTabBar::tab::first{border-left:1 solid #404040}#HexagonalColorWheel{qproperty-BGColor:#808080}#colorSlider::groove:horizontal{height:1;border-image:none}#colorSlider::handle:horizontal{width:8;margin:-8 -4}#colorSliderAddButton,#colorSliderSubButton{background:none;border-color:transparent;image-position:center center;min-height:16;padding:0;min-width:18}#colorSliderAddButton{image:url('../Default/imgs/black/scroll-right.svg')}#colorSliderSubButton{image:url('../Default/imgs/black/scroll-left.svg')}#PlainColorPageParts{border-bottom:1 solid #404040}#PlainColorPageParts QLineEdit{max-width:35}PaletteViewer DvScrollWidget QPushButton{border-top:0;margin-bottom:1;max-width:15;min-width:15}PaletteViewer DvScrollWidget #ScrollLeftButton{border-radius:0;margin-bottom:1;max-width:16;min-width:16}PaletteViewer DvScrollWidget #ScrollRightButton{border-radius:0;margin-left:1;margin-bottom:1;max-width:16;min-width:16}PaletteViewer QToolBar{background:none;border-bottom:1 solid #404040;padding:0;margin:0}PaletteViewer QToolBar::separator:horizontal{margin:0}PaletteViewer QToolBar QToolButton{margin:0 0 1 0;padding:1 0 2 0}#PageViewer{qproperty-TextColor:#000}#PaletteLockButton{border-radius:0;margin:0 0 1 1}#PaletteLockButton:checked{background-color:#C34040;border-color:#772626}#PaletteLockButton:checked:hover{background-color:#d57a7a;border-color:#772626}#WordButton{padding-right:0;padding-left:0}QDialog{background-color:#808080}QDialog #dialogButtonFrame{background-color:#767676;border-top:1 solid #404040}QDialog #dialogButtonFrame QPushButton{border-color:#525252;outline:0}QDialog #dialogButtonFrame QPushButton:focus{background-color:#B5C0D0;border-color:#485971;color:#000}QDialog #dialogButtonFrame QPushButton:focus:hover{background-color:#ced5e0}QDialog #dialogButtonFrame QPushButton:focus:pressed{background-color:#e1e1e1;border-color:#525252;color:#000}#SceneSettings QLabel{color:#000}#PreferencesPopup QListWidget{background-color:#949494;alternate-background-color:#949494;border:1 solid #404040;font-size:13}#PreferencesPopup QListWidget::item{border:0;padding:3}#PreferencesPopup QListWidget::item:hover{background-color:#9f9f9f;color:#000;background-color:#a9a9a9}#PreferencesPopup QListWidget::item:selected{background-color:#225baf;color:#FFFFFF}#ShortcutTree{border:1 solid #404040}#ShortcutTree::item{padding:1 0}#ShortcutTree QScrollBar:vertical{width:16;margin-right:-1}ProjectPopup QLabel{color:#000}#GearButton{qproperty-icon:url('../Default/imgs/black/gear.svg')}#SubfolderButton{qproperty-icon:url('../Default/imgs/black/subfolder.svg')}SchematicViewer{qproperty-TextColor:#000;qproperty-VerticalLineColor:#646464;qproperty-LevelColumnColor:#76b776;qproperty-VectorColumnColor:#c0c07a;qproperty-ChildColumnColor:#d69adb;qproperty-FullcolorColumnColor:#8bbdc1;qproperty-FxColumnColor:#82815d;qproperty-PaletteColumnColor:#2aab9a;qproperty-MeshColumnColor:#ac78d4;qproperty-ReferenceColumnColor:#ababab;qproperty-TableColor:#a4a4bf;qproperty-ActiveCameraColor:#6ba5de;qproperty-OtherCameraColor:#8f9c9e;qproperty-GroupColor:#6698c6;qproperty-PegColor:#be8a56;qproperty-SplineColor:#7bb821;qproperty-ActiveOutputColor:#6ba5de;qproperty-OtherOutputColor:#8f9c9e;qproperty-XsheetColor:#a4a4bf;qproperty-NormalFxColor:#8d9caf;qproperty-MacroFxColor:#ae8ca5;qproperty-ImageAdjustFxColor:#9c9ab4;qproperty-LayerBlendingFxColor:#709ba5;qproperty-MatteFxColor:#ba8585;qproperty-SchematicPreviewButtonBgOnColor:#c8c864;qproperty-SchematicPreviewButtonOnImage:url('../Default/imgs/black/x_prev_eye_on.svg');qproperty-SchematicPreviewButtonBgOffColor:#ababab;qproperty-SchematicPreviewButtonOffImage:url('../Default/imgs/black/x_prev_eye_off.svg');qproperty-SchematicCamstandButtonBgOnColor:#eb906b;qproperty-SchematicCamstandButtonOnImage:url('../Default/imgs/black/x_table_view_on.svg');qproperty-SchematicCamstandButtonTranspImage:url('../Default/imgs/black/x_table_view_transp.svg');qproperty-SchematicCamstandButtonBgOffColor:#ababab;qproperty-SchematicCamstandButtonOffImage:url('../Default/imgs/black/x_table_view_off.svg')}#SchematicBottomFrame{background-color:#808080;border:0;margin:0;padding:0}#SchematicBottomFrame QToolBar::separator:horizontal{margin:0}#SchematicBottomFrame QToolBar QToolButton{padding:0;margin:2}#SchematicSceneViewer{background-color:#737373;border-bottom:1 solid #404040}#FxSettingsTabBar::tab{border-top:1 solid #404040}#FxSettingsTabBar::tab::first,#FxSettingsTabBar::tab::only-one{border-left:1 solid #404040}FxSettings QToolBar{border-top:1 solid #404040;border-right:1 solid #404040;border-left:1 solid #404040;min-height:23;padding:3 0}FxSettings QToolBar QToolBar{border:0}#FxSettingsLabel{color:#000}#FxSettingsHelpButton{background-color:#80a0dc;color:#000;padding-top:0;padding-bottom:0}#FxSettingsHelpButton:hover{background-color:#a8bee7}#ScriptConsole{font-family:'Courier New',monospace;border:0;color:#000000;padding:3}#ScriptConsole QFrame{background-color:#dcdcdc}#ScriptConsole TPanelTitleBar{background-color:#5a5a5a}#TaskSheetItemLabel{color:#000}#Tasks QToolBar{border-bottom:1 solid #404040;margin:0;padding:0}#Tasks QToolBar QToolButton{margin:2 2 3 2}#ToolBar QToolBar{padding-left:2}#ToolOptions TPanelTitleBar{border-right:1 solid #404040;border-bottom:0}#CommandBar TPanelTitleBar{border-right:1 solid #404040;border-bottom:0}IconViewField{qproperty-ThicknessPixmap:url("../Default/imgs/black/selectiontool_thickness.svg")}#EditToolLockButton{spacing:0}#EditToolLockButton:hover{background:none}#EditToolLockButton::indicator{border:1 solid rgba(255,255,255,0);height:18;padding:0;width:18}#EditToolLockButton::indicator:unchecked{image:url('../Default/imgs/black/lock_off.svg')}#EditToolLockButton::indicator:checked{background-color:#C34040;border-color:#772626;image:url('../Default/imgs/black/lock_on.svg')}#EditToolLockButton::indicator:checked:hover{background-color:#d57a7a;border-color:#772626}PopupButton::menu-indicator{border-left:0;height:17;image:url('../Default/imgs/black/combo_downarrow.svg');width:10}PopupButton::menu-indicator:hover{image:url('../Default/imgs/black/combo_downarrow.svg')}PopupButton::menu-indicator:disabled{image:url('../Default/imgs/black/combo_downarrow_disabled.svg')}#Cap,#Join{padding:0 4 0 -8;max-width:32;min-width:32}#Cap QMenu,#Join QMenu{max-width:28;min-width:28}#Cap QMenu::item,#Join QMenu::item{max-width:28;min-width:28;padding:0}QToolBar#MediumPaddingToolBar QToolButton{padding-left:3;padding-right:3}QToolBar#WidePaddingToolBar QToolButton{padding-left:6;padding-right:6}#CommandBar{margin:0;padding:0;border:0}#CommandBar::separator:horizontal{margin-right:3;margin-left:3}#expandButton:checked{background-color:transparent;border-color:transparent;color:#000}#expandButton:checked:hover{background-color:#bbb;border-color:#525252}#expandButton:checked:pressed{background-color:#e1e1e1;border-color:#525252}#ComboViewerPanel Toolbar{border-bottom:1 solid #404040}#ComboViewerPanel Toolbar::separator:horizontal{margin:0 0 0 2}#ComboViewerPanel Toolbar QToolButton{margin:2 0 3 2}#ComboViewerToolOptions{border-bottom:1 solid #404040}#ComboViewer #ToolBarContainer,#ViewerPanel #ToolBarContainer,FlipBook #ToolBarContainer{background-color:transparent;border-top:2 solid #404040;border-bottom:1 solid #404040;padding-right:-1}#flipCustomize{margin-left:3}#flipCustomize::menu-button{background-color:transparent;width:35}#flipCustomize::menu-arrow{image:none}QToolBar#FlipConsolePlayToolBar::separator:horizontal{margin:0 3}QToolBar#FlipConsolePlayToolBar QToolButton{margin-top:2;margin-bottom:2;height:16;padding-left:1;padding-right:1}#ViewerFpsSlider{background-color:transparent;background-image:url('../Default/imgs/black/slider-groove.svg');background-position:center center;background-repeat:repeat-x;border:0;height:19;margin:0 3 0 37;max-width:300;min-width:0}#ViewerFpsSlider::sub-line:horizontal{subcontrol-origin:absolute;background-color:#a6a6a6;border:1 solid #525252;border-top-left-radius:2;border-bottom-left-radius:2;height:16;left:-33;width:14}#ViewerFpsSlider::add-line:horizontal{subcontrol-position:left;background-color:#a6a6a6;border:1 solid #525252;border-top-right-radius:2;border-bottom-right-radius:2;left:18;height:16;image-position:center center;width:13}#ViewerFpsSlider::handle::horizontal{background-color:#a6a6a6;border:1 solid #404040;border-radius:2;margin:2 0 3 0;min-width:9;width:9;max-width:9}FlipSlider{qproperty-PBHeight:15;qproperty-PBOverlay:url('../Default/imgs/black/flipslider.svg');qproperty-PBColorMarginLeft:1;qproperty-PBColorMarginTop:2;qproperty-PBColorMarginRight:1;qproperty-PBColorMarginBottom:2;qproperty-PBMarker:url('../Default/imgs/black/flipmarker.svg');qproperty-PBMarkerMarginLeft:3;qproperty-PBMarkerMarginRight:3;qproperty-notStartedColor:#8b2525;qproperty-startedColor:#00a808;qproperty-baseColor:#676767;qproperty-finishedColor:#676767}Ruler{qproperty-ParentBGColor:#c0c0c0;qproperty-ScaleColor:#000}#RulerToolOptionValues{color:#000}#xsheetArea,#ScrollArea{background-color:#6c6c6c;border:0}#xsheetScrollArea{border:0}#cornerWidget QToolButton{padding:0}#xsheetColumnAreaMenu_Preview{background-color:#E6E678}#xsheetColumnAreaMenu_Lock{background-color:#F5F5F5}#xsheetColumnAreaMenu_Camstand{background-color:#FFA480}#xsheetColumnAreaMenu_Preview,#xsheetColumnAreaMenu_Lock,#xsheetColumnAreaMenu_Camstand{color:#000}#noteTextEdit{color:#000}XsheetViewer{qproperty-TextColor:#000;qproperty-BGColor:#929292;qproperty-LightLineColor:#616161;qproperty-MarkerLineColor:#000;qproperty-VerticalLineColor:#646464;qproperty-VerticalLineHeadColor:#393939;qproperty-PreviewFrameTextColor:#000eb6;qproperty-CurrentRowBgColor:#B5C0D0;qproperty-OnionSkinAreaBgColor:#858585;qproperty-EmptyColumnHeadColor:#808080;qproperty-SelectedColumnTextColor:#9e0000;qproperty-EmptyCellColor:#7c7c7c;qproperty-NotEmptyColumnColor:#8a8a8a;qproperty-SelectedEmptyCellColor:#b3b3b3;qproperty-LevelColumnColor:#76b776;qproperty-LevelColumnBorderColor:#496549;qproperty-SelectedLevelColumnColor:#9bc59b;qproperty-VectorColumnColor:#c0c07a;qproperty-VectorColumnBorderColor:#71714a;qproperty-SelectedVectorColumnColor:#cdcda0;qproperty-ChildColumnColor:#d69adb;qproperty-ChildColumnBorderColor:#9c53a3;qproperty-SelectedChildColumnColor:#e3c2e6;qproperty-FullcolorColumnColor:#8bbdc1;qproperty-FullcolorColumnBorderColor:#577476;qproperty-SelectedFullcolorColumnColor:#afcdd0;qproperty-FxColumnColor:#82815d;qproperty-FxColumnBorderColor:#404039;qproperty-SelectedFxColumnColor:#97967b;qproperty-ReferenceColumnColor:#ababab;qproperty-ReferenceColumnBorderColor:#6b6b6b;qproperty-SelectedReferenceColumnColor:#c4c4c4;qproperty-PaletteColumnColor:#2aab9a;qproperty-PaletteColumnBorderColor:#173e39;qproperty-SelectedPaletteColumnColor:#40c8b6;qproperty-MeshColumnColor:#ac78d4;qproperty-MeshColumnBorderColor:#6b418c;qproperty-SelectedMeshColumnColor:#c3a2dd;qproperty-SoundTextColumnColor:#c8c8c8;qproperty-SoundTextColumnBorderColor:#8c8c8c;qproperty-SelectedSoundTextColumnColor:#e2e2e2;qproperty-SoundColumnColor:#acba82;qproperty-SoundColumnBorderColor:#656b51;qproperty-SelectedSoundColumnColor:#c0c9a6;qproperty-SoundColumnHlColor:#f5ffe6;qproperty-SoundColumnTrackColor:#5a642d;qproperty-ColumnHeadPastelizer:#fff;qproperty-SelectedColumnHead:#bed2f0;qproperty-LightLightBGColor:#808080;qproperty-LightBGColor:#f0f0f0;qproperty-DarkBGColor:#e1e1e1;qproperty-DarkLineColor:#969696;qproperty-XsheetColumnNameBgColor:rgba(0,0,0,0);qproperty-XsheetDragBarHighlightColor:rgba(255,255,255,0.5);qproperty-XsheetPreviewButtonBgOnColor:#c8c864;qproperty-XsheetPreviewButtonOnImage:url('../Default/imgs/black/x_prev_eye_on.svg');qproperty-XsheetPreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetPreviewButtonOffImage:url('../Default/imgs/black/x_prev_eye_off.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');qproperty-XsheetCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetCamstandButtonOffImage:url('../Default/imgs/black/x_table_view_off.svg');qproperty-XsheetLockButtonBgOnColor:rgba(255,255,255,0.3);qproperty-XsheetLockButtonOnImage:url('../Default/imgs/black/x_lock_on.svg');qproperty-XsheetLockButtonBgOffColor:rgba(255,255,255,0);qproperty-XsheetLockButtonOffImage:url('../Default/imgs/black/x_lock_off.svg');qproperty-XsheetConfigButtonBgColor:rgba(255,255,255,0);qproperty-XsheetConfigButtonImage:url('../Default/imgs/black/x_config.svg');qproperty-TimelinePreviewButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOnImage:url('../Default/imgs/black/timeline_toggle_on.svg');qproperty-TimelinePreviewButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelinePreviewButtonOffImage:url('../Default/imgs/black/timeline_toggle_off.svg');qproperty-TimelineCamstandButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOnImage:url('../Default/imgs/black/timeline_toggle_on.svg');qproperty-TimelineCamstandButtonTranspImage:url('../Default/imgs/black/timeline_toggle_transp.svg');qproperty-TimelineCamstandButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineCamstandButtonOffImage:url('../Default/imgs/black/timeline_toggle_off.svg');qproperty-TimelineLockButtonBgOnColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOnImage:url('../Default/imgs/black/timeline_toggle_on.svg');qproperty-TimelineLockButtonBgOffColor:rgba(255,255,255,0);qproperty-TimelineLockButtonOffImage:url('../Default/imgs/black/timeline_toggle_off.svg');qproperty-TimelineConfigButtonBgColor:rgba(255,255,255,0);qproperty-TimelineConfigButtonImage:url('../Default/imgs/black/timeline_config.svg');qproperty-LayerHeaderPreviewImage:url('../Default/imgs/black/layer_header_prev_eye.svg');qproperty-LayerHeaderPreviewOverImage:url('../Default/imgs/black/layer_header_prev_eye_over.svg');qproperty-LayerHeaderCamstandImage:url('../Default/imgs/black/layer_header_table_view.svg');qproperty-LayerHeaderCamstandOverImage:url('../Default/imgs/black/layer_header_table_view_over.svg');qproperty-LayerHeaderLockImage:url('../Default/imgs/black/lock_on.svg');qproperty-LayerHeaderLockOverImage:url('../Default/imgs/black/lock_on_over.svg')}#XSheetToolbar{margin:0;padding:0;border:0}#XSheetToolbar QToolButton{padding:0;margin:4 1;min-height:19;height:19}#XSheetToolbar::separator:horizontal{margin:0 4}#FunctionEditor QToolBar{border-bottom:1 solid #404040}#FunctionEditor QToolBar QToolBar{border:0}#FunctionEditor QToolBar QLabel{margin-left:5}#FunctionEditor QToolBar QToolButton{height:18}#FunctionEditorTree{border-top:1 solid #404040}FunctionTreeView{qproperty-TextColor:#000;qproperty-CurrentTextColor:#a70000}FunctionPanel{qproperty-BGColor:#5a5a5a;qproperty-ValueLineColor:#4d4d4d;qproperty-FrameLineColor:#4d4d4d;qproperty-OtherCurvesColor:#c5c5c5;qproperty-RulerBackground:#676767;qproperty-TextColor:#000;qproperty-SubColor:#fff;qproperty-SelectedColor:#fcae06}SpreadsheetViewer{qproperty-LightLightBGColor:#808080;qproperty-CurrentRowBgColor:#B5C0D0;qproperty-LightLineColor:#616161;qproperty-MarkerLineColor:#000;qproperty-BGColor:#8a8a8a;qproperty-VerticalLineColor:#646464;qproperty-KeyFrameColor:#db8b36;qproperty-KeyFrameBorderColor:#7b4a16;qproperty-SelectedKeyFrameColor:#dea466;qproperty-InBetweenColor:#c2c2b0;qproperty-InBetweenBorderColor:#636356;qproperty-SelectedInBetweenColor:#d6d6cf;qproperty-SelectedEmptyColor:#b3b3b3;qproperty-SelectedSceneRangeEmptyColor:#d2d2d2;qproperty-TextColor:#000;qproperty-ColumnHeaderBorderColor:#393939;qproperty-SelectedColumnTextColor:#9e0000}#ExpressionField{background-color:#fff;border:1 solid #6b6b6b;margin:0}#FunctionSegmentViewerLinkButton{background-image:url('../Default/imgs/black/segment_unlinked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:hover{background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:checked{background-image:url('../Default/imgs/black/segment_linked.svg');background-repeat:no-repeat}#FunctionSegmentViewerLinkButton:disabled{background-image:url('../Default/imgs/black/segment_disabled.svg');background-repeat:no-repeat} \ No newline at end of file diff --git a/stuff/doc/LICENSE/LICENSE_winink.txt b/stuff/doc/LICENSE/LICENSE_winink.txt new file mode 100644 index 0000000..d45cec5 --- /dev/null +++ b/stuff/doc/LICENSE/LICENSE_winink.txt @@ -0,0 +1,23 @@ +Windows Pointer Input Message support code files from Krita +Copyright (c) 2017 Alvin Wong + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/stuff/doc/img/Thumbs.db b/stuff/doc/img/Thumbs.db deleted file mode 100644 index 6083fa0..0000000 Binary files a/stuff/doc/img/Thumbs.db and /dev/null differ diff --git a/stuff/library/clapperboards/images/board1.png b/stuff/library/clapperboards/images/board1.png new file mode 100644 index 0000000..2d03ef7 Binary files /dev/null and b/stuff/library/clapperboards/images/board1.png differ diff --git a/stuff/library/clapperboards/preset_sample.clapperboard b/stuff/library/clapperboards/preset_sample.clapperboard new file mode 100644 index 0000000..bcc3fd3 --- /dev/null +++ b/stuff/library/clapperboards/preset_sample.clapperboard @@ -0,0 +1,190 @@ + + + 24 + + + + + ScenePath_Full + + + "Scene file path" + + + 0.15 0.566708 0.7 0.0433166 + + + 300 + + + 0 0 0 255 + + + Verdana 0 0 + + + + + UserName + + + "User name" + + + 0.7 0.9 0.2 0.05 + + + 300 + + + 0 128 0 255 + + + Verdana 0 1 + + + + + CurrentDate + + + "Rendering date" + + + 0.1 0.9 0.2 0.05 + + + 300 + + + 0 0 0 255 + + + Verdana 0 0 + + + + + FreeText + + + "Type some description here" + + + 0.15 0.629176 0.55 0.248329 + + + "" + + + 40 + + + 0 0 64 255 + + + Verdana 0 0 + + + + + Duration_SecFrame + + + "Scene duration" + + + 0.351376 0.424454 0.3 0.125546 + + + 300 + + + 0 0 0 255 + + + Verdana 0 0 + + + + + SceneName + + + Scene + + + 0.35 0.25 0.3 0.2 + + + 300 + + + 0 0 0 255 + + + Verdana 1 0 + + + + + FreeText + + + "Episode #" + + + 0.15 0.3 0.2 0.2 + + + "#" + + + 120 + + + 0 0 0 255 + + + Verdana 0 0 + + + + + ProjectName + + + Title + + + 0.15 0.1 0.7 0.15 + + + 300 + + + 0 0 0 255 + + + Verdana 1 0 + + + + + Image + + + Background + + + 0 0 1 1 + + + 1 "clapperboards\\images\\board1.png" + + + 0 + + + + diff --git a/stuff/library/custom styles/Thumbs.db b/stuff/library/custom styles/Thumbs.db deleted file mode 100644 index b30123c..0000000 Binary files a/stuff/library/custom styles/Thumbs.db and /dev/null differ diff --git a/stuff/library/particles/Thumbs.db b/stuff/library/particles/Thumbs.db deleted file mode 100644 index e6106fd..0000000 Binary files a/stuff/library/particles/Thumbs.db and /dev/null differ diff --git a/stuff/library/textures/Thumbs.db b/stuff/library/textures/Thumbs.db deleted file mode 100644 index be9208d..0000000 Binary files a/stuff/library/textures/Thumbs.db and /dev/null differ diff --git a/stuff/profiles/layouts/fxs/STD_iwa_TextFx.xml b/stuff/profiles/layouts/fxs/STD_iwa_TextFx.xml new file mode 100644 index 0000000..aab4c54 --- /dev/null +++ b/stuff/profiles/layouts/fxs/STD_iwa_TextFx.xml @@ -0,0 +1,17 @@ + + + + targetType + columnIndex + text + hAlign + center + width + height + font + textColor + boxColor + showBorder + + + diff --git a/stuff/profiles/layouts/fxs/fxs.lst b/stuff/profiles/layouts/fxs/fxs.lst index 126bc35..b7c1e33 100644 --- a/stuff/profiles/layouts/fxs/fxs.lst +++ b/stuff/profiles/layouts/fxs/fxs.lst @@ -147,6 +147,7 @@ STD_particlesFx STD_iwa_TiledParticlesFx STD_iwa_TimeCodeFx + STD_iwa_TextFx STD_colorEmbossFx diff --git a/stuff/profiles/layouts/rooms/Default/room1.ini b/stuff/profiles/layouts/rooms/Default/room1.ini index 8abbfaa..aec7553 100644 --- a/stuff/profiles/layouts/rooms/Default/room1.ini +++ b/stuff/profiles/layouts/rooms/Default/room1.ini @@ -5,7 +5,7 @@ pane_1\name=FilmStrip pane_1\geometry=@Rect(1168 34 342 514) pane_2\name=LevelPalette pane_2\geometry=@Rect(421 706 739 290) -pane_2\viewtype=0 +pane_2\viewtype=2 pane_3\name=StyleEditor pane_3\geometry=@Rect(1168 556 342 440) pane_4\name=SceneViewer diff --git a/stuff/profiles/layouts/rooms/Default/room3.ini b/stuff/profiles/layouts/rooms/Default/room3.ini index 93fd5b2..7d56a5a 100644 --- a/stuff/profiles/layouts/rooms/Default/room3.ini +++ b/stuff/profiles/layouts/rooms/Default/room3.ini @@ -9,7 +9,7 @@ pane_3\name=ToolOptions pane_3\geometry=@Rect(0 0 1920 26) pane_4\name=LevelPalette pane_4\geometry=@Rect(1131 34 398 217) -pane_4\viewtype=0 +pane_4\viewtype=2 pane_5\name=StyleEditor pane_5\geometry=@Rect(1131 259 398 737) hierarchy="-1 1 [ 3 [ 1 0 [ 4 5 ] 2 ] ] " diff --git a/stuff/profiles/layouts/rooms/Default/room5.ini b/stuff/profiles/layouts/rooms/Default/room5.ini index 2b25991..d21f88d 100644 --- a/stuff/profiles/layouts/rooms/Default/room5.ini +++ b/stuff/profiles/layouts/rooms/Default/room5.ini @@ -11,7 +11,7 @@ pane_4\name=Xsheet pane_4\geometry=@Rect(43 646 1181 350) pane_5\name=LevelPalette pane_5\geometry=@Rect(1232 320 688 130) -pane_5\viewtype=0 +pane_5\viewtype=2 pane_6\name=StyleEditor pane_6\geometry=@Rect(1232 458 688 538) pane_7\name=StudioPalette diff --git a/stuff/profiles/layouts/rooms/Default/room9.ini b/stuff/profiles/layouts/rooms/Default/room9.ini index 9f9cd43..a1bf55f 100644 --- a/stuff/profiles/layouts/rooms/Default/room9.ini +++ b/stuff/profiles/layouts/rooms/Default/room9.ini @@ -20,4 +20,4 @@ pane_5\name=ToolOptions pane_5\geometry=@Rect(0 0 1920 26) pane_6\name=LevelPalette pane_6\geometry=@Rect(0 521 238 190) -pane_6\viewtype=0 +pane_6\viewtype=2 diff --git a/toonz/cmake/BundleInfo.plist.in b/toonz/cmake/BundleInfo.plist.in index f4bb670..59a4388 100644 --- a/toonz/cmake/BundleInfo.plist.in +++ b/toonz/cmake/BundleInfo.plist.in @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion English CFBundleExecutable - OpenToonz_1.2 + OpenToonz CFBundleGetInfoString CFBundleIconFile diff --git a/toonz/install/SystemVar.ini b/toonz/install/SystemVar.ini index f21022e..0301d50 100644 --- a/toonz/install/SystemVar.ini +++ b/toonz/install/SystemVar.ini @@ -1,11 +1,11 @@ [General] -TOONZCACHEROOT="/Applications/OpenToonz/OpenToonz_1.2_stuff/cache" -TOONZCONFIG="/Applications/OpenToonz/OpenToonz_1.2_stuff/config" -TOONZFXPRESETS="/Applications/OpenToonz/OpenToonz_1.2_stuff/fxs" -TOONZLIBRARY="/Applications/OpenToonz/OpenToonz_1.2_stuff/library" -TOONZPROFILES="/Applications/OpenToonz/OpenToonz_1.2_stuff/profiles" -OpenToonzPROFILES="/Applications/OpenToonz/OpenToonz_1.2_stuff/profiles" -TOONZPROJECTS="/Applications/OpenToonz/OpenToonz_1.2_stuff/projects" -TOONZROOT="/Applications/OpenToonz/OpenToonz_1.2_stuff" -OPENTOONZROOT="/Applications/OpenToonz/OpenToonz_1.2_stuff" -TOONZSTUDIOPALETTE="/Applications/OpenToonz/OpenToonz_1.2_stuff/studiopalette" +TOONZCACHEROOT="/Applications/OpenToonz/OpenToonz_stuff/cache" +TOONZCONFIG="/Applications/OpenToonz/OpenToonz_stuff/config" +TOONZFXPRESETS="/Applications/OpenToonz/OpenToonz_stuff/fxs" +TOONZLIBRARY="/Applications/OpenToonz/OpenToonz_stuff/library" +TOONZPROFILES="/Applications/OpenToonz/OpenToonz_stuff/profiles" +OpenToonzPROFILES="/Applications/OpenToonz/OpenToonz_stuff/profiles" +TOONZPROJECTS="/Applications/OpenToonz/OpenToonz_stuff/projects" +TOONZROOT="/Applications/OpenToonz/OpenToonz_stuff" +OPENTOONZROOT="/Applications/OpenToonz/OpenToonz_stuff" +TOONZSTUDIOPALETTE="/Applications/OpenToonz/OpenToonz_stuff/studiopalette" diff --git a/toonz/sources/CMakeLists.txt b/toonz/sources/CMakeLists.txt index 0f37a0e..662afbd 100644 --- a/toonz/sources/CMakeLists.txt +++ b/toonz/sources/CMakeLists.txt @@ -599,5 +599,11 @@ if(BUILD_ENV_APPLE) $ ) # add capability for retina displays - set_target_properties(OpenToonz_1.2 PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/../cmake/BundleInfo.plist.in) + set_target_properties(OpenToonz PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/../cmake/BundleInfo.plist.in) +endif() + +if(BUILD_ENV_UNIXLIKE) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/xdg-data/io.github.OpenToonz.appdata.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/xdg-data/io.github.OpenToonz.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/xdg-data/io.github.OpenToonz.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/256x256/apps) endif() diff --git a/toonz/sources/colorfx/strokestyles.cpp b/toonz/sources/colorfx/strokestyles.cpp index 29d1e9e..8c47fa7 100644 --- a/toonz/sources/colorfx/strokestyles.cpp +++ b/toonz/sources/colorfx/strokestyles.cpp @@ -2105,7 +2105,7 @@ void TBraidStrokeStyle::drawStroke(const TColorFunction *cf, swap += step; if (swap > (period / 3.0)) { swapcount++; - tswap(braid[0], braid[1 + (swapcount & 1)]); + std::swap(braid[0], braid[1 + (swapcount & 1)]); swap -= period / 3.0; } } @@ -2188,7 +2188,7 @@ void TBraidStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const { swap += step; if (swap > (period / 3.0)) { swapcount++; - tswap(braid[0], braid[1 + (swapcount & 1)]); + std::swap(braid[0], braid[1 + (swapcount & 1)]); swap -= period / 3.0; } } diff --git a/toonz/sources/common/tapptools/tenv.cpp b/toonz/sources/common/tapptools/tenv.cpp index 47bb8af..05528cb 100644 --- a/toonz/sources/common/tapptools/tenv.cpp +++ b/toonz/sources/common/tapptools/tenv.cpp @@ -1,9 +1,8 @@ - - #include "tenv.h" #include "tsystem.h" #include "tconvert.h" #include "tfilepath_io.h" +#include "tversion.h" #include #include @@ -24,6 +23,7 @@ TOfflineGL::Imp *MacOfflineGenerator1(const TDimension &dim) { #include using namespace TEnv; +using namespace TVER; //========================================================= // @@ -40,9 +40,8 @@ const std::map systemPathMap{ class EnvGlobals { // singleton - std::string m_applicationName; + ToonzVersion m_version; std::string m_applicationVersion; - std::string m_applicationVersionWithoutRevision; std::string m_applicationFullName; std::string m_moduleName; std::string m_rootVarName; @@ -57,7 +56,10 @@ class EnvGlobals { // singleton // path values specified with command line arguments std::map m_argPathValues; - EnvGlobals() : m_stuffDir(0) { setWorkingDirectory(); } + EnvGlobals() : m_stuffDir(0) { + setWorkingDirectory(); + init(); + } public: ~EnvGlobals() { delete m_stuffDir; } @@ -74,10 +76,9 @@ public: QString settingsPath; #ifdef MACOSX - settingsPath = - QString::fromStdString(getApplicationName()) + QString("_") + - QString::fromStdString(getApplicationVersionWithoutRevision()) + - QString(".app") + QString("/Contents/Resources/SystemVar.ini"); + settingsPath = QString::fromStdString(getApplicationName()) + + QString(".app") + + QString("/Contents/Resources/SystemVar.ini"); #else /* Generic Unix */ // TODO: use QStandardPaths::ConfigLocation when we drop Qt4 settingsPath = QDir::homePath(); @@ -132,6 +133,13 @@ public: #endif } + TFilePath getSystemVarPathValue(std::string varName) { + // return if the path is registered by command line argument + std::string argVar = getArgPathValue(varName); + if (argVar != "") return TFilePath(argVar); + return TFilePath(getSystemVarValue(varName)); + } + TFilePath getStuffDir() { if (m_stuffDir) return *m_stuffDir; if (m_isPortable) @@ -153,31 +161,30 @@ public: profilesDir + "env" + (TSystem::getUserName().toStdString() + ".env"); } - void setApplication(std::string applicationName, - std::string applicationVersion, std::string revision) { - m_applicationName = applicationName; - m_applicationVersionWithoutRevision = applicationVersion; - if (!revision.empty()) { - m_applicationVersion = - m_applicationVersionWithoutRevision + "." + revision; + void init() { + if (m_version.getAppRevision() != 0) { + m_applicationVersion = m_version.getAppVersionString() + "." + + m_version.getAppRevisionString(); } else { - m_applicationVersion = m_applicationVersionWithoutRevision; + m_applicationVersion = m_version.getAppVersionString(); } - m_applicationFullName = m_applicationName + " " + m_applicationVersion; - m_moduleName = m_applicationName; - m_rootVarName = toUpper(m_applicationName) + "ROOT"; + + m_applicationFullName = m_version.getAppName() + " " + m_applicationVersion; + m_moduleName = m_version.getAppName(); + m_rootVarName = toUpper(m_version.getAppName()) + "ROOT"; #ifdef _WIN32 - m_registryRoot = TFilePath("SOFTWARE\\OpenToonz\\") + m_applicationName + - applicationVersion; + // from v1.3, registry root is moved to SOFTWARE\\OpenToonz\\OpenToonz + m_registryRoot = + TFilePath("SOFTWARE\\OpenToonz\\") + m_version.getAppName(); #endif - m_systemVarPrefix = m_applicationName; + m_systemVarPrefix = m_version.getAppName(); updateEnvFile(); } - std::string getApplicationName() { return m_applicationName; } + std::string getApplicationName() { return m_version.getAppName(); } std::string getApplicationVersion() { return m_applicationVersion; } std::string getApplicationVersionWithoutRevision() { - return m_applicationVersionWithoutRevision; + return m_version.getAppVersionString(); } TFilePath getEnvFile() { return m_envFile; } @@ -469,17 +476,6 @@ void Variable::assignValue(std::string value) { //=================================================================== -void TEnv::setApplication(std::string applicationName, - std::string applicationVersion, - std::string revision) { - EnvGlobals::instance()->setApplication(applicationName, applicationVersion, - revision); - -#ifdef LEVO_MACOSX - TOfflineGL::defineImpGenerator(MacOfflineGenerator1); -#endif -} - std::string TEnv::getApplicationName() { return EnvGlobals::instance()->getApplicationName(); } @@ -521,11 +517,7 @@ std::string TEnv::getSystemVarStringValue(std::string varName) { } TFilePath TEnv::getSystemVarPathValue(std::string varName) { - EnvGlobals *eg = EnvGlobals::instance(); - // return if the path is registered by command line argument - std::string argVar = eg->getArgPathValue(varName); - if (argVar != "") return TFilePath(argVar); - return TFilePath(eg->getSystemVarValue(varName)); + return EnvGlobals::instance()->getSystemVarPathValue(varName); } TFilePathSet TEnv::getSystemVarPathSetValue(std::string varName) { @@ -583,14 +575,6 @@ void TEnv::setStuffDir(const TFilePath &stuffDir) { EnvGlobals::instance()->setStuffDir(stuffDir); } -TFilePath TEnv::getDllRelativeDir() { - return EnvGlobals::instance()->getDllRelativeDir(); -} - -void TEnv::setDllRelativeDir(const TFilePath &dllRelativeDir) { - EnvGlobals::instance()->setDllRelativeDir(dllRelativeDir); -} - void TEnv::saveAllEnvVariables() { VariableSet::instance()->save(); } bool TEnv::setArgPathValue(std::string key, std::string value) { diff --git a/toonz/sources/common/tcache/timagecache.cpp b/toonz/sources/common/tcache/timagecache.cpp index 63913bc..2513700 100644 --- a/toonz/sources/common/tcache/timagecache.cpp +++ b/toonz/sources/common/tcache/timagecache.cpp @@ -33,7 +33,6 @@ #include "traster.h" //#include "tstopwatch.h" -#include "tconvert.h" #include "tbigmemorymanager.h" #include "tstream.h" diff --git a/toonz/sources/common/tfx/tfx.cpp b/toonz/sources/common/tfx/tfx.cpp index 125a69e..2b94fdc 100644 --- a/toonz/sources/common/tfx/tfx.cpp +++ b/toonz/sources/common/tfx/tfx.cpp @@ -61,6 +61,7 @@ void skipChild(TIStream &is) { if (is.isBeginEndTag()) is.matchTag(tagName); is.closeChild(); } + if (is.isBeginEndTag()) is.matchTag(tagName); } } @@ -365,8 +366,8 @@ void TFx::linkParams(TFx *fx) { assert(m_imp->checkLinks()); assert(fx->m_imp->checkLinks()); - tswap(m_imp->m_next, fx->m_imp->m_next); - tswap(m_imp->m_next->m_prev, fx->m_imp->m_next->m_prev); + std::swap(m_imp->m_next, fx->m_imp->m_next); + std::swap(m_imp->m_next->m_prev, fx->m_imp->m_next->m_prev); assert(m_imp->checkLinks()); assert(fx->m_imp->checkLinks()); diff --git a/toonz/sources/common/tfx/zeraryFx.cpp b/toonz/sources/common/tfx/zeraryFx.cpp index b52fe1d..3864aaa 100644 --- a/toonz/sources/common/tfx/zeraryFx.cpp +++ b/toonz/sources/common/tfx/zeraryFx.cpp @@ -7,7 +7,6 @@ // TnzBase includes #include "tparamset.h" #include "tdoubleparam.h" -#include "tzeraryfx.h" #include "tfxparam.h" #include "tparamuiconcept.h" diff --git a/toonz/sources/common/tiio/tiio.cpp b/toonz/sources/common/tiio/tiio.cpp index 7e10801..d664add 100644 --- a/toonz/sources/common/tiio/tiio.cpp +++ b/toonz/sources/common/tiio/tiio.cpp @@ -2,7 +2,6 @@ #include "tiio.h" -#include "tiio.h" #include "tiio_jpg.h" #include "tproperty.h" diff --git a/toonz/sources/common/tiio/tiio_bmp.cpp b/toonz/sources/common/tiio/tiio_bmp.cpp index 243a1f7..a20f164 100644 --- a/toonz/sources/common/tiio/tiio_bmp.cpp +++ b/toonz/sources/common/tiio/tiio_bmp.cpp @@ -598,6 +598,9 @@ public: void flush() override { fflush(m_chan); } void writeLine(char *buffer) override; + + // for now opentoonz does not support bmp format with alpha channel + bool writeAlphaSupported() const override { return false; } }; //--------------------------------------------------------- diff --git a/toonz/sources/common/tiio/tiio_jpg.cpp b/toonz/sources/common/tiio/tiio_jpg.cpp index ec3917c..25a454d 100644 --- a/toonz/sources/common/tiio/tiio_jpg.cpp +++ b/toonz/sources/common/tiio/tiio_jpg.cpp @@ -9,6 +9,7 @@ //#include "../compatibility/tnz4.h" #include "tiio_jpg.h" +#include "tiio_jpg_exif.h" #include "tproperty.h" #include "tpixel.h" @@ -76,10 +77,36 @@ void JpgReader::open(FILE *file) { m_cinfo.err->error_exit = tnz_error_exit; jpeg_create_decompress(&m_cinfo); + m_chan = file; jpeg_stdio_src(&m_cinfo, m_chan); + jpeg_save_markers(&m_cinfo, JPEG_APP0 + 1, 0xffff); // EXIF bool ret = jpeg_read_header(&m_cinfo, TRUE); - ret = ret && jpeg_start_decompress(&m_cinfo); + + bool resolutionFoundInExif = false; + jpeg_saved_marker_ptr mark; + for (mark = m_cinfo.marker_list; NULL != mark; mark = mark->next) { + switch (mark->marker) { + case JPEG_APP0 + 1: // EXIF + JpgExifReader exifReader; + exifReader.process_EXIF(mark->data - 2, mark->data_length); + if (exifReader.containsResolution()) { + int resUnit = exifReader.getResolutionUnit(); + resolutionFoundInExif = true; + if (resUnit == 1 || resUnit == 2) { // no unit(1) or inch(2) + m_info.m_dpix = (double)exifReader.getXResolution(); + m_info.m_dpiy = (double)exifReader.getYResolution(); + } else if (resUnit == 3) { // centimeter(3); + m_info.m_dpix = (double)exifReader.getXResolution() * 2.54; + m_info.m_dpiy = (double)exifReader.getYResolution() * 2.54; + } else // ignore millimeter(4) and micrometer(5) cases for now + resolutionFoundInExif = false; + } + break; + } + } + + ret = ret && jpeg_start_decompress(&m_cinfo); if (!ret) return; int row_stride = m_cinfo.output_width * m_cinfo.output_components; @@ -91,6 +118,17 @@ void JpgReader::open(FILE *file) { m_info.m_samplePerPixel = 3; m_info.m_valid = true; m_isOpen = true; + + if (!resolutionFoundInExif && (m_cinfo.saw_JFIF_marker != 0) && + (m_cinfo.X_density != 1) && (m_cinfo.Y_density != 1)) { + if (m_cinfo.density_unit == 1) { + m_info.m_dpix = (double)m_cinfo.X_density; + m_info.m_dpiy = (double)m_cinfo.Y_density; + } else if (m_cinfo.density_unit == 2) { + m_info.m_dpix = (double)m_cinfo.X_density * 2.54; + m_info.m_dpiy = (double)m_cinfo.Y_density * 2.54; + } + } } void JpgReader::readLine(char *buffer, int x0, int x1, int shrink) { @@ -164,15 +202,42 @@ public: m_cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&m_cinfo); + + // save dpi always in JFIF header, instead of EXIF + m_cinfo.write_JFIF_header = 1; + m_cinfo.JFIF_major_version = 1; + m_cinfo.JFIF_minor_version = 2; + m_cinfo.X_density = (UINT16)info.m_dpix; + m_cinfo.Y_density = (UINT16)info.m_dpiy; + m_cinfo.density_unit = 1; // dot per inch + m_cinfo.write_Adobe_marker = 0; + if (!m_properties) m_properties = new Tiio::JpgWriterProperties(); - jpeg_set_quality( - &m_cinfo, - ((TIntProperty *)(m_properties->getProperty("Quality")))->getValue(), - TRUE); + int quality = + ((TIntProperty *)(m_properties->getProperty("Quality")))->getValue(); + + jpeg_set_quality(&m_cinfo, quality, TRUE); m_cinfo.smoothing_factor = ((TIntProperty *)(m_properties->getProperty("Smoothing")))->getValue(); + // set horizontal and vertical chroma subsampling factor to encoder + // according to the quality value. + if (quality >= 70) { // none chroma-subsampling (4:4:4) + m_cinfo.comp_info[0].h_samp_factor = 1; + m_cinfo.comp_info[0].v_samp_factor = 1; + } else if (quality >= 30) { // medium chroma-subsampling (4:2:2) + m_cinfo.comp_info[0].h_samp_factor = 2; + m_cinfo.comp_info[0].v_samp_factor = 1; + } else { // quality < 30, high chroma-subsampling (4:1:1) + m_cinfo.comp_info[0].h_samp_factor = 2; + m_cinfo.comp_info[0].v_samp_factor = 2; + } + m_cinfo.comp_info[1].h_samp_factor = 1; + m_cinfo.comp_info[1].v_samp_factor = 1; + m_cinfo.comp_info[2].h_samp_factor = 1; + m_cinfo.comp_info[2].v_samp_factor = 1; + int row_stride = m_cinfo.image_width * m_cinfo.input_components; m_buffer = (*m_cinfo.mem->alloc_sarray)((j_common_ptr)&m_cinfo, JPOOL_IMAGE, row_stride, 1); @@ -208,6 +273,9 @@ public: } jpeg_write_scanlines(&m_cinfo, m_buffer, 1); } + + // jpeg format does not support alpha channel + bool writeAlphaSupported() const override { return false; } }; //---- diff --git a/toonz/sources/common/tiio/tiio_jpg_exif.cpp b/toonz/sources/common/tiio/tiio_jpg_exif.cpp new file mode 100644 index 0000000..c7613dd --- /dev/null +++ b/toonz/sources/common/tiio/tiio_jpg_exif.cpp @@ -0,0 +1,1057 @@ +/*------------------------------------------------------------- +tiio_jpg_exif.cpp +Based on source code of a public domain software "Exif Jpeg header manipulation +tool (jhead)" by Matthias Wandel. +For now it is used only for obtaining resolution values. +http://www.sentex.net/~mwandel/jhead/ +-------------------------------------------------------------*/ +#include "tiio_jpg_exif.h" +#include +#include + +// for debug +#define ShowTags 0 +#define DumpExifMap 0 + +namespace { + +typedef unsigned char uchar; +const int BytesPerFormat[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8}; +//-------------------------------------------------------------------------- +// Describes tag values +const int TAG_X_RESOLUTION = 0x011A; +const int TAG_Y_RESOLUTION = 0x011B; +const int TAG_RESOLUTION_UNIT = 0x0128; +#ifdef ReadAllTags +const int TAG_INTEROP_INDEX = 0x0001; +const int TAG_INTEROP_VERSION = 0x0002; +const int TAG_IMAGE_WIDTH = 0x0100; +const int TAG_IMAGE_LENGTH = 0x0101; +const int TAG_BITS_PER_SAMPLE = 0x0102; +const int TAG_COMPRESSION = 0x0103; +const int TAG_PHOTOMETRIC_INTERP = 0x0106; +const int TAG_FILL_ORDER = 0x010A; +const int TAG_DOCUMENT_NAME = 0x010D; +const int TAG_IMAGE_DESCRIPTION = 0x010E; +const int TAG_MAKE = 0x010F; +const int TAG_MODEL = 0x0110; +const int TAG_SRIP_OFFSET = 0x0111; +const int TAG_ORIENTATION = 0x0112; +const int TAG_SAMPLES_PER_PIXEL = 0x0115; +const int TAG_ROWS_PER_STRIP = 0x0116; +const int TAG_STRIP_BYTE_COUNTS = 0x0117; +const int TAG_PLANAR_CONFIGURATION = 0x011C; +const int TAG_TRANSFER_FUNCTION = 0x012D; +const int TAG_SOFTWARE = 0x0131; +const int TAG_DATETIME = 0x0132; +const int TAG_ARTIST = 0x013B; +const int TAG_WHITE_POINT = 0x013E; +const int TAG_PRIMARY_CHROMATICITIES = 0x013F; +const int TAG_TRANSFER_RANGE = 0x0156; +const int TAG_JPEG_PROC = 0x0200; +const int TAG_THUMBNAIL_OFFSET = 0x0201; +const int TAG_THUMBNAIL_LENGTH = 0x0202; +const int TAG_Y_CB_CR_COEFFICIENTS = 0x0211; +const int TAG_Y_CB_CR_SUB_SAMPLING = 0x0212; +const int TAG_Y_CB_CR_POSITIONING = 0x0213; +const int TAG_REFERENCE_BLACK_WHITE = 0x0214; +const int TAG_RELATED_IMAGE_WIDTH = 0x1001; +const int TAG_RELATED_IMAGE_LENGTH = 0x1002; +const int TAG_CFA_REPEAT_PATTERN_DIM = 0x828D; +const int TAG_CFA_PATTERN1 = 0x828E; +const int TAG_BATTERY_LEVEL = 0x828F; +const int TAG_COPYRIGHT = 0x8298; +const int TAG_EXPOSURETIME = 0x829A; +const int TAG_FNUMBER = 0x829D; +const int TAG_IPTC_NAA = 0x83BB; +const int TAG_EXIF_OFFSET = 0x8769; +const int TAG_INTER_COLOR_PROFILE = 0x8773; +const int TAG_EXPOSURE_PROGRAM = 0x8822; +const int TAG_SPECTRAL_SENSITIVITY = 0x8824; +const int TAG_GPSINFO = 0x8825; +const int TAG_ISO_EQUIVALENT = 0x8827; +const int TAG_OECF = 0x8828; +const int TAG_EXIF_VERSION = 0x9000; +const int TAG_DATETIME_ORIGINAL = 0x9003; +const int TAG_DATETIME_DIGITIZED = 0x9004; +const int TAG_COMPONENTS_CONFIG = 0x9101; +const int TAG_CPRS_BITS_PER_PIXEL = 0x9102; +const int TAG_SHUTTERSPEED = 0x9201; +const int TAG_APERTURE = 0x9202; +const int TAG_BRIGHTNESS_VALUE = 0x9203; +const int TAG_EXPOSURE_BIAS = 0x9204; +const int TAG_MAXAPERTURE = 0x9205; +const int TAG_SUBJECT_DISTANCE = 0x9206; +const int TAG_METERING_MODE = 0x9207; +const int TAG_LIGHT_SOURCE = 0x9208; +const int TAG_FLASH = 0x9209; +const int TAG_FOCALLENGTH = 0x920A; +const int TAG_SUBJECTAREA = 0x9214; +const int TAG_MAKER_NOTE = 0x927C; +const int TAG_USERCOMMENT = 0x9286; +const int TAG_SUBSEC_TIME = 0x9290; +const int TAG_SUBSEC_TIME_ORIG = 0x9291; +const int TAG_SUBSEC_TIME_DIG = 0x9292; + +const int TAG_WINXP_TITLE = 0x9c9b; // Windows XP - not part of exif standard. +const int TAG_WINXP_COMMENT = + 0x9c9c; // Windows XP - not part of exif standard. +const int TAG_WINXP_AUTHOR = 0x9c9d; // Windows XP - not part of exif standard. +const int TAG_WINXP_KEYWORDS = + 0x9c9e; // Windows XP - not part of exif standard. +const int TAG_WINXP_SUBJECT = + 0x9c9f; // Windows XP - not part of exif standard. + +const int TAG_FLASH_PIX_VERSION = 0xA000; +const int TAG_COLOR_SPACE = 0xA001; +const int TAG_PIXEL_X_DIMENSION = 0xA002; +const int TAG_PIXEL_Y_DIMENSION = 0xA003; +const int TAG_RELATED_AUDIO_FILE = 0xA004; +const int TAG_INTEROP_OFFSET = 0xA005; +const int TAG_FLASH_ENERGY = 0xA20B; +const int TAG_SPATIAL_FREQ_RESP = 0xA20C; +const int TAG_FOCAL_PLANE_XRES = 0xA20E; +const int TAG_FOCAL_PLANE_YRES = 0xA20F; +const int TAG_FOCAL_PLANE_UNITS = 0xA210; +const int TAG_SUBJECT_LOCATION = 0xA214; +const int TAG_EXPOSURE_INDEX = 0xA215; +const int TAG_SENSING_METHOD = 0xA217; +const int TAG_FILE_SOURCE = 0xA300; +const int TAG_SCENE_TYPE = 0xA301; +const int TAG_CFA_PATTERN = 0xA302; +const int TAG_CUSTOM_RENDERED = 0xA401; +const int TAG_EXPOSURE_MODE = 0xA402; +const int TAG_WHITEBALANCE = 0xA403; +const int TAG_DIGITALZOOMRATIO = 0xA404; +const int TAG_FOCALLENGTH_35MM = 0xA405; +const int TAG_SCENE_CAPTURE_TYPE = 0xA406; +const int TAG_GAIN_CONTROL = 0xA407; +const int TAG_CONTRAST = 0xA408; +const int TAG_SATURATION = 0xA409; +const int TAG_SHARPNESS = 0xA40A; +const int TAG_DISTANCE_RANGE = 0xA40C; +const int TAG_IMAGE_UNIQUE_ID = 0xA420; +#endif + +typedef struct { + unsigned short Tag; + char *Desc; +} TagTable_t; + +const TagTable_t TagTable[] = { + {TAG_X_RESOLUTION, "XResolution"}, + {TAG_Y_RESOLUTION, "YResolution"}, + {TAG_RESOLUTION_UNIT, "ResolutionUnit"}, +#ifdef ReadAllTags + {TAG_INTEROP_INDEX, "InteropIndex"}, + {TAG_INTEROP_VERSION, "InteropVersion"}, + {TAG_IMAGE_WIDTH, "ImageWidth"}, + {TAG_IMAGE_LENGTH, "ImageLength"}, + {TAG_BITS_PER_SAMPLE, "BitsPerSample"}, + {TAG_COMPRESSION, "Compression"}, + {TAG_PHOTOMETRIC_INTERP, "PhotometricInterpretation"}, + {TAG_FILL_ORDER, "FillOrder"}, + {TAG_DOCUMENT_NAME, "DocumentName"}, + {TAG_IMAGE_DESCRIPTION, "ImageDescription"}, + {TAG_MAKE, "Make"}, + {TAG_MODEL, "Model"}, + {TAG_SRIP_OFFSET, "StripOffsets"}, + {TAG_ORIENTATION, "Orientation"}, + {TAG_SAMPLES_PER_PIXEL, "SamplesPerPixel"}, + {TAG_ROWS_PER_STRIP, "RowsPerStrip"}, + {TAG_STRIP_BYTE_COUNTS, "StripByteCounts"}, + {TAG_PLANAR_CONFIGURATION, "PlanarConfiguration"}, + {TAG_TRANSFER_FUNCTION, "TransferFunction"}, + {TAG_SOFTWARE, "Software"}, + {TAG_DATETIME, "DateTime"}, + {TAG_ARTIST, "Artist"}, + {TAG_WHITE_POINT, "WhitePoint"}, + {TAG_PRIMARY_CHROMATICITIES, "PrimaryChromaticities"}, + {TAG_TRANSFER_RANGE, "TransferRange"}, + {TAG_JPEG_PROC, "JPEGProc"}, + {TAG_THUMBNAIL_OFFSET, "ThumbnailOffset"}, + {TAG_THUMBNAIL_LENGTH, "ThumbnailLength"}, + {TAG_Y_CB_CR_COEFFICIENTS, "YCbCrCoefficients"}, + {TAG_Y_CB_CR_SUB_SAMPLING, "YCbCrSubSampling"}, + {TAG_Y_CB_CR_POSITIONING, "YCbCrPositioning"}, + {TAG_REFERENCE_BLACK_WHITE, "ReferenceBlackWhite"}, + {TAG_RELATED_IMAGE_WIDTH, "RelatedImageWidth"}, + {TAG_RELATED_IMAGE_LENGTH, "RelatedImageLength"}, + {TAG_CFA_REPEAT_PATTERN_DIM, "CFARepeatPatternDim"}, + {TAG_CFA_PATTERN1, "CFAPattern"}, + {TAG_BATTERY_LEVEL, "BatteryLevel"}, + {TAG_COPYRIGHT, "Copyright"}, + {TAG_EXPOSURETIME, "ExposureTime"}, + {TAG_FNUMBER, "FNumber"}, + {TAG_IPTC_NAA, "IPTC/NAA"}, + {TAG_EXIF_OFFSET, "ExifOffset"}, + {TAG_INTER_COLOR_PROFILE, "InterColorProfile"}, + {TAG_EXPOSURE_PROGRAM, "ExposureProgram"}, + {TAG_SPECTRAL_SENSITIVITY, "SpectralSensitivity"}, + {TAG_GPSINFO, "GPS Dir offset"}, + {TAG_ISO_EQUIVALENT, "ISOSpeedRatings"}, + {TAG_OECF, "OECF"}, + {TAG_EXIF_VERSION, "ExifVersion"}, + {TAG_DATETIME_ORIGINAL, "DateTimeOriginal"}, + {TAG_DATETIME_DIGITIZED, "DateTimeDigitized"}, + {TAG_COMPONENTS_CONFIG, "ComponentsConfiguration"}, + {TAG_CPRS_BITS_PER_PIXEL, "CompressedBitsPerPixel"}, + {TAG_SHUTTERSPEED, "ShutterSpeedValue"}, + {TAG_APERTURE, "ApertureValue"}, + {TAG_BRIGHTNESS_VALUE, "BrightnessValue"}, + {TAG_EXPOSURE_BIAS, "ExposureBiasValue"}, + {TAG_MAXAPERTURE, "MaxApertureValue"}, + {TAG_SUBJECT_DISTANCE, "SubjectDistance"}, + {TAG_METERING_MODE, "MeteringMode"}, + {TAG_LIGHT_SOURCE, "LightSource"}, + {TAG_FLASH, "Flash"}, + {TAG_FOCALLENGTH, "FocalLength"}, + {TAG_MAKER_NOTE, "MakerNote"}, + {TAG_USERCOMMENT, "UserComment"}, + {TAG_SUBSEC_TIME, "SubSecTime"}, + {TAG_SUBSEC_TIME_ORIG, "SubSecTimeOriginal"}, + {TAG_SUBSEC_TIME_DIG, "SubSecTimeDigitized"}, + {TAG_WINXP_TITLE, "Windows-XP Title"}, + {TAG_WINXP_COMMENT, "Windows-XP comment"}, + {TAG_WINXP_AUTHOR, "Windows-XP author"}, + {TAG_WINXP_KEYWORDS, "Windows-XP keywords"}, + {TAG_WINXP_SUBJECT, "Windows-XP subject"}, + {TAG_FLASH_PIX_VERSION, "FlashPixVersion"}, + {TAG_COLOR_SPACE, "ColorSpace"}, + {TAG_PIXEL_X_DIMENSION, "ExifImageWidth"}, + {TAG_PIXEL_Y_DIMENSION, "ExifImageLength"}, + {TAG_RELATED_AUDIO_FILE, "RelatedAudioFile"}, + {TAG_INTEROP_OFFSET, "InteroperabilityOffset"}, + {TAG_FLASH_ENERGY, "FlashEnergy"}, + {TAG_SPATIAL_FREQ_RESP, "SpatialFrequencyResponse"}, + {TAG_FOCAL_PLANE_XRES, "FocalPlaneXResolution"}, + {TAG_FOCAL_PLANE_YRES, "FocalPlaneYResolution"}, + {TAG_FOCAL_PLANE_UNITS, "FocalPlaneResolutionUnit"}, + {TAG_SUBJECT_LOCATION, "SubjectLocation"}, + {TAG_EXPOSURE_INDEX, "ExposureIndex"}, + {TAG_SENSING_METHOD, "SensingMethod"}, + {TAG_FILE_SOURCE, "FileSource"}, + {TAG_SCENE_TYPE, "SceneType"}, + {TAG_CFA_PATTERN, "CFA Pattern"}, + {TAG_CUSTOM_RENDERED, "CustomRendered"}, + {TAG_EXPOSURE_MODE, "ExposureMode"}, + {TAG_WHITEBALANCE, "WhiteBalance"}, + {TAG_DIGITALZOOMRATIO, "DigitalZoomRatio"}, + {TAG_FOCALLENGTH_35MM, "FocalLengthIn35mmFilm"}, + {TAG_SUBJECTAREA, "SubjectArea"}, + {TAG_SCENE_CAPTURE_TYPE, "SceneCaptureType"}, + {TAG_GAIN_CONTROL, "GainControl"}, + {TAG_CONTRAST, "Contrast"}, + {TAG_SATURATION, "Saturation"}, + {TAG_SHARPNESS, "Sharpness"}, + {TAG_DISTANCE_RANGE, "SubjectDistanceRange"}, + {TAG_IMAGE_UNIQUE_ID, "ImageUniqueId"}, +#endif +}; + +const int TAG_TABLE_SIZE = (sizeof(TagTable) / sizeof(TagTable_t)); + +const int TRUE = 1; +const int FALSE = 0; +} + +//-------------------------------------------------------------------------- +// Convert a 16 bit unsigned value from file's native byte order +//-------------------------------------------------------------------------- +int JpgExifReader::Get16u(void *Short) { + if (MotorolaOrder) { + return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1]; + } else { + return (((uchar *)Short)[1] << 8) | ((uchar *)Short)[0]; + } +} + +//-------------------------------------------------------------------------- +// Convert a 32 bit signed value from file's native byte order +//-------------------------------------------------------------------------- +int JpgExifReader::Get32s(void *Long) { + if (MotorolaOrder) { + return (((char *)Long)[0] << 24) | (((uchar *)Long)[1] << 16) | + (((uchar *)Long)[2] << 8) | (((uchar *)Long)[3] << 0); + } else { + return (((char *)Long)[3] << 24) | (((uchar *)Long)[2] << 16) | + (((uchar *)Long)[1] << 8) | (((uchar *)Long)[0] << 0); + } +} + +//-------------------------------------------------------------------------- +// Convert a 32 bit unsigned value from file's native byte order +//-------------------------------------------------------------------------- +unsigned JpgExifReader::Get32u(void *Long) { + return (unsigned)Get32s(Long) & 0xffffffff; +} + +//-------------------------------------------------------------------------- +// Display a number as one of its many formats +//-------------------------------------------------------------------------- +void JpgExifReader::PrintFormatNumber(void *ValuePtr, int Format, + int ByteCount) { + int s, n; + + for (n = 0; n < 16; n++) { + switch (Format) { + case FMT_SBYTE: + case FMT_BYTE: + printf("%02x", *(uchar *)ValuePtr); + s = 1; + break; + case FMT_USHORT: + printf("%d", Get16u(ValuePtr)); + s = 2; + break; + case FMT_ULONG: + case FMT_SLONG: + printf("%d", Get32s(ValuePtr)); + s = 4; + break; + case FMT_SSHORT: + printf("%hd", (signed short)Get16u(ValuePtr)); + s = 2; + break; + case FMT_URATIONAL: + printf("%u/%u", Get32s(ValuePtr), Get32s(4 + (char *)ValuePtr)); + s = 8; + break; + + case FMT_SRATIONAL: + printf("%d/%d", Get32s(ValuePtr), Get32s(4 + (char *)ValuePtr)); + s = 8; + break; + + case FMT_SINGLE: + printf("%f", (double)*(float *)ValuePtr); + s = 8; + break; + case FMT_DOUBLE: + printf("%f", *(double *)ValuePtr); + s = 8; + break; + default: + printf("Unknown format %d:", Format); + return; + } + ByteCount -= s; + if (ByteCount <= 0) break; + printf(", "); + ValuePtr = (void *)((char *)ValuePtr + s); + } + if (n >= 16) printf("..."); +} + +//-------------------------------------------------------------------------- +// Evaluate number, be it int, rational, or float from directory. +//-------------------------------------------------------------------------- +double JpgExifReader::ConvertAnyFormat(void *ValuePtr, int Format) { + double Value; + Value = 0; + + switch (Format) { + case FMT_SBYTE: + Value = *(signed char *)ValuePtr; + break; + case FMT_BYTE: + Value = *(uchar *)ValuePtr; + break; + + case FMT_USHORT: + Value = Get16u(ValuePtr); + break; + case FMT_ULONG: + Value = Get32u(ValuePtr); + break; + + case FMT_URATIONAL: + case FMT_SRATIONAL: { + int Num, Den; + Num = Get32s(ValuePtr); + Den = Get32s(4 + (char *)ValuePtr); + if (Den == 0) { + Value = 0; + } else { + if (Format == FMT_SRATIONAL) { + Value = (double)Num / Den; + } else { + Value = (double)(unsigned)Num / (double)(unsigned)Den; + } + } + break; + } + + case FMT_SSHORT: + Value = (signed short)Get16u(ValuePtr); + break; + case FMT_SLONG: + Value = Get32s(ValuePtr); + break; + + // Not sure if this is correct (never seen float used in Exif format) + case FMT_SINGLE: + Value = (double)*(float *)ValuePtr; + break; + case FMT_DOUBLE: + Value = *(double *)ValuePtr; + break; + + default: + std::cout << "Illegal format code " << Format << " in Exif header" + << std::endl; + } + return Value; +} + +//-------------------------------------------------------------------------- + +void JpgExifReader::process_EXIF(unsigned char *ExifSection, + unsigned int length) { + unsigned int FirstOffset; + +#ifdef ReadAllTags + FocalplaneXRes = 0; + FocalplaneUnits = 0; + ExifImageWidth = 0; + NumOrientations = 0; + DirWithThumbnailPtrs = NULL; +#endif + + if (ShowTags) printf("Exif header %u bytes long\n", length); + + { // Check the EXIF header component + static uchar ExifHeader[] = "Exif\0\0"; + if (memcmp(ExifSection + 2, ExifHeader, 6)) { + std::cout << "Incorrect Exif header" << std::endl; + return; + } + } + + if (memcmp(ExifSection + 8, "II", 2) == 0) { + if (ShowTags) printf("Exif section in Intel order\n"); + MotorolaOrder = 0; + } else { + if (memcmp(ExifSection + 8, "MM", 2) == 0) { + if (ShowTags) printf("Exif section in Motorola order\n"); + MotorolaOrder = 1; + } else { + std::cout << "Invalid Exif alignment marker." << std::endl; + return; + } + } + + // Check the next value for correctness. + if (Get16u(ExifSection + 10) != 0x2a) { + std::cout << "Invalid Exif start (1)" << std::endl; + return; + } + + FirstOffset = Get32u(ExifSection + 12); + if (FirstOffset < 8 || FirstOffset > 16) { + if (FirstOffset < 16 || FirstOffset > length - 16) { + std::cout << "invalid offset for first Exif IFD value" << std::endl; + return; + } + // Usually set to 8, but other values valid too. + std::cout << "Suspicious offset of first Exif IFD value" << std::endl; + } + + // First directory starts 16 bytes in. All offset are relative to 8 bytes in. + ProcessExifDir(ExifSection + 8 + FirstOffset, ExifSection + 8, length - 8, 0); + +#ifdef ReadAllTags + ImageInfo.ThumbnailAtEnd = + ImageInfo.ThumbnailOffset >= ImageInfo.LargestExifOffset ? TRUE : FALSE; + + if (DumpExifMap) { + unsigned a, b; + printf("Map: %05d- End of exif\n", length - 8); + for (a = 0; a < length - 8; a += 10) { + printf("Map: %05d ", a); + for (b = 0; b < 10; b++) printf(" %02x", *(ExifSection + 8 + a + b)); + printf("\n"); + } + } + + // Compute the CCD width, in millimeters. + if (FocalplaneXRes != 0 && ExifImageWidth != 0) { + // Note: With some cameras, its not possible to compute this correctly + // because + // they don't adjust the indicated focal plane resolution units when using + // less + // than maximum resolution, so the CCDWidth value comes out too small. + // Nothing + // that Jhad can do about it - its a camera problem. + ImageInfo.CCDWidth = + (float)(ExifImageWidth * FocalplaneUnits / FocalplaneXRes); + + if (ImageInfo.FocalLength && ImageInfo.FocalLength35mmEquiv == 0) { + // Compute 35 mm equivalent focal length based on sensor geometry if we + // haven't + // already got it explicitly from a tag. + ImageInfo.FocalLength35mmEquiv = + (int)(ImageInfo.FocalLength / ImageInfo.CCDWidth * 36 + 0.5); + } + } +#endif +} + +//-------------------------------------------------------------------------- +// Process one of the nested EXIF directories. +//-------------------------------------------------------------------------- +void JpgExifReader::ProcessExifDir(unsigned char *DirStart, + unsigned char *OffsetBase, + unsigned ExifLength, int NestingLevel) { + int de; + int a; + int NumDirEntries; + unsigned ThumbnailOffset = 0; + unsigned ThumbnailSize = 0; + char IndentString[25]; + + if (NestingLevel > 4) { + std::cout << "Maximum Exif directory nesting exceeded (corrupt Exif header)" + << std::endl; + return; + } + + memset(IndentString, ' ', 25); + IndentString[NestingLevel * 4] = '\0'; + + NumDirEntries = Get16u(DirStart); +#define DIR_ENTRY_ADDR(Start, Entry) (Start + 2 + 12 * (Entry)) + + { + unsigned char *DirEnd; + DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries); + if (DirEnd + 4 > (OffsetBase + ExifLength)) { + if (DirEnd + 2 == OffsetBase + ExifLength || + DirEnd == OffsetBase + ExifLength) { + // Version 1.3 of jhead would truncate a bit too much. + // This also caught later on as well. + } else { + std::cout << "Illegally sized Exif subdirectory (" << NumDirEntries + << "entries)" << std::endl; + return; + } + } + if (DumpExifMap) { + printf("Map: %05u-%05u: Directory\n", (int)(DirStart - OffsetBase), + (int)(DirEnd + 4 - OffsetBase)); + } + } + + if (ShowTags) { + printf("(dir has %d entries)\n", NumDirEntries); + } + + for (de = 0; de < NumDirEntries; de++) { + int Tag, Format, Components; + unsigned char *ValuePtr; + int ByteCount; + unsigned char *DirEntry; + DirEntry = DIR_ENTRY_ADDR(DirStart, de); + + Tag = Get16u(DirEntry); + Format = Get16u(DirEntry + 2); + Components = Get32u(DirEntry + 4); + + if ((Format - 1) >= NUM_FORMATS) { + // (-1) catches illegal zero case as unsigned underflows to positive + // large. + std::cout << "Illegal number format " << Format << " for tag " << Tag + << " in Exif" << std::endl; + continue; + } + + if ((unsigned)Components > 0x10000) { + std::cout << "Too many components " << Components << " for tag " << Tag + << " in Exif"; + continue; + } + + ByteCount = Components * BytesPerFormat[Format]; + + if (ByteCount > 4) { + unsigned OffsetVal; + OffsetVal = Get32u(DirEntry + 8); + // If its bigger than 4 bytes, the dir entry contains an offset. + if (OffsetVal + ByteCount > ExifLength) { + // Bogus pointer offset and / or bytecount value + std::cout << "Illegal value pointer for tag " << Tag << " in Exif"; + continue; + } + ValuePtr = OffsetBase + OffsetVal; + +#ifdef ReadAllTags + if (OffsetVal > ImageInfo.LargestExifOffset) { + ImageInfo.LargestExifOffset = OffsetVal; + } +#endif + + if (DumpExifMap) { + printf("Map: %05u-%05u: Data for tag %04x\n", OffsetVal, + OffsetVal + ByteCount, Tag); + } + } else { + // 4 bytes or less and value is in the dir entry itself + ValuePtr = DirEntry + 8; + } + +#ifdef ReadAllTags + if (Tag == TAG_MAKER_NOTE) { + if (ShowTags) { + printf("%s Maker note: ", IndentString); + } + // ProcessMakerNote(ValuePtr, ByteCount, OffsetBase, ExifLength); + continue; + } + + if (ShowTags) { + // Show tag name + for (a = 0;; a++) { + if (a >= TAG_TABLE_SIZE) { + printf("%s Unknown Tag %04x Value = ", IndentString, Tag); + break; + } + if (TagTable[a].Tag == Tag) { + printf("%s %s = ", IndentString, TagTable[a].Desc); + break; + } + } + + // Show tag value. + switch (Format) { + case FMT_BYTE: + if (ByteCount > 1) { + printf("%.*ls\n", ByteCount / 2, (wchar_t *)ValuePtr); + } else { + PrintFormatNumber(ValuePtr, Format, ByteCount); + printf("\n"); + } + break; + + case FMT_UNDEFINED: + // Undefined is typically an ascii string. + + case FMT_STRING: + // String arrays printed without function call (different from int + // arrays) + { + int NoPrint = 0; + printf("\""); + for (a = 0; a < ByteCount; a++) { + if (ValuePtr[a] >= 32) { + putchar(ValuePtr[a]); + NoPrint = 0; + } else { + // Avoiding indicating too many unprintable characters of + // proprietary + // bits of binary information this program may not know how to + // parse. + if (!NoPrint && a != ByteCount - 1) { + putchar('?'); + NoPrint = 1; + } + } + } + printf("\"\n"); + } + break; + + default: + // Handle arrays of numbers later (will there ever be?) + PrintFormatNumber(ValuePtr, Format, ByteCount); + printf("\n"); + } + } +#endif + // Extract useful components of tag + switch (Tag) { +#ifdef ReadAllTags + case TAG_MAKE: + strncpy(ImageInfo.CameraMake, (char *)ValuePtr, + ByteCount < 31 ? ByteCount : 31); + break; + + case TAG_MODEL: + strncpy(ImageInfo.CameraModel, (char *)ValuePtr, + ByteCount < 39 ? ByteCount : 39); + break; + + case TAG_DATETIME_ORIGINAL: + // If we get a DATETIME_ORIGINAL, we use that one. + strncpy(ImageInfo.DateTime, (char *)ValuePtr, 19); + // Fallthru... + + case TAG_DATETIME_DIGITIZED: + case TAG_DATETIME: + if (!isdigit(static_cast(ImageInfo.DateTime[0]))) { + // If we don't already have a DATETIME_ORIGINAL, use whatever + // time fields we may have. + strncpy(ImageInfo.DateTime, (char *)ValuePtr, 19); + } + + if (ImageInfo.numDateTimeTags >= MAX_DATE_COPIES) { + std::cout << "More than " << MAX_DATE_COPIES + << " date fields in Exif. This is nuts" << std::endl; + break; + } + ImageInfo.DateTimeOffsets[ImageInfo.numDateTimeTags++] = + (char *)ValuePtr - (char *)OffsetBase; + break; + + case TAG_WINXP_COMMENT: + if (ImageInfo.Comments[0]) { // We already have a jpeg comment. + // Already have a comment (probably windows comment), skip this one. + if (ShowTags) + printf("Windows XP commend and other comment in header\n"); + break; // Already have a windows comment, skip this one. + } + + if (ByteCount > 1) { + if (ByteCount > MAX_COMMENT_SIZE) ByteCount = MAX_COMMENT_SIZE; + memcpy(ImageInfo.Comments, ValuePtr, ByteCount); + ImageInfo.CommentWidthchars = ByteCount / 2; + } + break; + + case TAG_USERCOMMENT: + if (ImageInfo.Comments[0]) { // We already have a jpeg comment. + // Already have a comment (probably windows comment), skip this one. + if (ShowTags) printf("Multiple comments in exif header\n"); + break; // Already have a windows comment, skip this one. + } + + // Comment is often padded with trailing spaces. Remove these first. + for (a = ByteCount;;) { + a--; + if ((ValuePtr)[a] == ' ') { + (ValuePtr)[a] = '\0'; + } else { + break; + } + if (a == 0) break; + } + + // Copy the comment + { + int msiz = ExifLength - (ValuePtr - OffsetBase); + if (msiz > ByteCount) msiz = ByteCount; + if (msiz > MAX_COMMENT_SIZE - 1) msiz = MAX_COMMENT_SIZE - 1; + if (msiz > 5 && memcmp(ValuePtr, "ASCII", 5) == 0) { + for (a = 5; a < 10 && a < msiz; a++) { + int c = (ValuePtr)[a]; + if (c != '\0' && c != ' ') { + strncpy(ImageInfo.Comments, (char *)ValuePtr + a, msiz - a); + break; + } + } + } else { + strncpy(ImageInfo.Comments, (char *)ValuePtr, msiz); + } + } + break; + + case TAG_FNUMBER: + // Simplest way of expressing aperture, so I trust it the most. + // (overwrite previously computd value if there is one) + ImageInfo.ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_APERTURE: + case TAG_MAXAPERTURE: + // More relevant info always comes earlier, so only use this field if we + // don't + // have appropriate aperture information yet. + if (ImageInfo.ApertureFNumber == 0) { + ImageInfo.ApertureFNumber = + (float)exp(ConvertAnyFormat(ValuePtr, Format) * log(2) * 0.5); + } + break; + + case TAG_FOCALLENGTH: + // Nice digital cameras actually save the focal length as a function + // of how farthey are zoomed in. + ImageInfo.FocalLength = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_SUBJECT_DISTANCE: + // Inidcates the distacne the autofocus camera is focused to. + // Tends to be less accurate as distance increases. + ImageInfo.Distance = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_EXPOSURETIME: + // Simplest way of expressing exposure time, so I trust it most. + // (overwrite previously computd value if there is one) + ImageInfo.ExposureTime = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_SHUTTERSPEED: + // More complicated way of expressing exposure time, so only use + // this value if we don't already have it from somewhere else. + if (ImageInfo.ExposureTime == 0) { + ImageInfo.ExposureTime = + (float)(1 / exp(ConvertAnyFormat(ValuePtr, Format) * log(2))); + } + break; + + case TAG_FLASH: + ImageInfo.FlashUsed = (int)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_ORIENTATION: + if (NumOrientations >= 2) { + // Can have another orientation tag for the thumbnail, but if there's + // a third one, things are strange. + std::cout << "More than two orientation in Exif" << std::endl; + break; + } + OrientationPtr[NumOrientations] = ValuePtr; + OrientationNumFormat[NumOrientations] = Format; + if (NumOrientations == 0) { + ImageInfo.Orientation = (int)ConvertAnyFormat(ValuePtr, Format); + } + if (ImageInfo.Orientation < 0 || ImageInfo.Orientation > 8) { + std::cout << "Undefined rotation value " << ImageInfo.Orientation + << " in Exif" << std::endl; + } + NumOrientations += 1; + break; + + case TAG_PIXEL_Y_DIMENSION: + case TAG_PIXEL_X_DIMENSION: + // Use largest of height and width to deal with images that have been + // rotated to portrait format. + a = (int)ConvertAnyFormat(ValuePtr, Format); + if (ExifImageWidth < a) ExifImageWidth = a; + break; + + case TAG_FOCAL_PLANE_XRES: + FocalplaneXRes = ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_FOCAL_PLANE_UNITS: + switch ((int)ConvertAnyFormat(ValuePtr, Format)) { + case 1: + FocalplaneUnits = 25.4; + break; // inch + case 2: + // According to the information I was using, 2 means meters. + // But looking at the Cannon powershot's files, inches is the only + // sensible value. + FocalplaneUnits = 25.4; + break; + + case 3: + FocalplaneUnits = 10; + break; // centimeter + case 4: + FocalplaneUnits = 1; + break; // millimeter + case 5: + FocalplaneUnits = .001; + break; // micrometer + } + break; + + case TAG_EXPOSURE_BIAS: + ImageInfo.ExposureBias = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_WHITEBALANCE: + ImageInfo.Whitebalance = (int)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_LIGHT_SOURCE: + ImageInfo.LightSource = (int)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_METERING_MODE: + ImageInfo.MeteringMode = (int)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_EXPOSURE_PROGRAM: + ImageInfo.ExposureProgram = (int)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_EXPOSURE_INDEX: + if (ImageInfo.ISOequivalent == 0) { + // Exposure index and ISO equivalent are often used interchangeably, + // so we will do the same in jhead. + // http://photography.about.com/library/glossary/bldef_ei.htm + ImageInfo.ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format); + } + break; + + case TAG_EXPOSURE_MODE: + ImageInfo.ExposureMode = (int)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_ISO_EQUIVALENT: + ImageInfo.ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_DIGITALZOOMRATIO: + ImageInfo.DigitalZoomRatio = (float)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_THUMBNAIL_OFFSET: + ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format); + DirWithThumbnailPtrs = DirStart; + break; + + case TAG_THUMBNAIL_LENGTH: + ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format); + ImageInfo.ThumbnailSizeOffset = ValuePtr - OffsetBase; + break; + + case TAG_EXIF_OFFSET: + if (ShowTags) printf("%s Exif Dir:", IndentString); + + case TAG_INTEROP_OFFSET: + if (Tag == TAG_INTEROP_OFFSET && ShowTags) + printf("%s Interop Dir:", IndentString); + { + unsigned char *SubdirStart; + SubdirStart = OffsetBase + Get32u(ValuePtr); + if (SubdirStart < OffsetBase || SubdirStart > OffsetBase + ExifLength) { + std::cout << "Illegal Exif or interop ofset directory link" + << std::endl; + } else { + ProcessExifDir(SubdirStart, OffsetBase, ExifLength, NestingLevel + 1); + } + continue; + } + break; + + case TAG_GPSINFO: + if (ShowTags) printf("%s GPS info dir:", IndentString); + { + unsigned char *SubdirStart; + SubdirStart = OffsetBase + Get32u(ValuePtr); + if (SubdirStart < OffsetBase || SubdirStart > OffsetBase + ExifLength) { + std::cout << "Illegal GPS directory link in Exif" << std::endl; + } else { + // ProcessGpsInfo(SubdirStart, OffsetBase, ExifLength); + } + continue; + } + break; + + case TAG_FOCALLENGTH_35MM: + // The focal length equivalent 35 mm is a 2.2 tag (defined as of April + // 2002) + // if its present, use it to compute equivalent focal length instead of + // computing it from sensor geometry and actual focal length. + ImageInfo.FocalLength35mmEquiv = + (unsigned)ConvertAnyFormat(ValuePtr, Format); + break; + + case TAG_DISTANCE_RANGE: + // Three possible standard values: + // 1 = macro, 2 = close, 3 = distant + ImageInfo.DistanceRange = (int)ConvertAnyFormat(ValuePtr, Format); + break; + +#endif + + case TAG_X_RESOLUTION: + if (NestingLevel == + 0) { // Only use the values from the top level directory + ImageInfo.xResolution = (float)ConvertAnyFormat(ValuePtr, Format); + // if yResolution has not been set, use the value of xResolution + if (ImageInfo.yResolution == 0.0) + ImageInfo.yResolution = ImageInfo.xResolution; + } + break; + + case TAG_Y_RESOLUTION: + if (NestingLevel == + 0) { // Only use the values from the top level directory + ImageInfo.yResolution = (float)ConvertAnyFormat(ValuePtr, Format); + // if xResolution has not been set, use the value of yResolution + if (ImageInfo.xResolution == 0.0) + ImageInfo.xResolution = ImageInfo.yResolution; + } + break; + + case TAG_RESOLUTION_UNIT: + if (NestingLevel == + 0) { // Only use the values from the top level directory + ImageInfo.ResolutionUnit = (int)ConvertAnyFormat(ValuePtr, Format); + } + break; + } + } + +#ifdef ReadAllTags + { + // In addition to linking to subdirectories via exif tags, + // there's also a potential link to another directory at the end of each + // directory. this has got to be the result of a committee! + unsigned char *SubdirStart; + unsigned Offset; + + if (DIR_ENTRY_ADDR(DirStart, NumDirEntries) + 4 <= + OffsetBase + ExifLength) { + Offset = Get32u(DirStart + 2 + 12 * NumDirEntries); + if (Offset) { + SubdirStart = OffsetBase + Offset; + if (SubdirStart > OffsetBase + ExifLength || SubdirStart < OffsetBase) { + if (SubdirStart > OffsetBase && + SubdirStart < OffsetBase + ExifLength + 20) { + // Jhead 1.3 or earlier would crop the whole directory! + // As Jhead produces this form of format incorrectness, + // I'll just let it pass silently + if (ShowTags) + printf("Thumbnail removed with Jhead 1.3 or earlier\n"); + } else { + std::cout << "Illegal subdirectory link in Exif header" + << std::endl; + } + } else { + if (SubdirStart <= OffsetBase + ExifLength) { + if (ShowTags) printf("%s Continued directory ", IndentString); + ProcessExifDir(SubdirStart, OffsetBase, ExifLength, + NestingLevel + 1); + } + } + if (Offset > ImageInfo.LargestExifOffset) { + ImageInfo.LargestExifOffset = Offset; + } + } + } else { + // The exif header ends before the last next directory pointer. + } + } + + if (ThumbnailOffset) { + ImageInfo.ThumbnailAtEnd = FALSE; + + if (DumpExifMap) { + printf("Map: %05d-%05d: Thumbnail\n", ThumbnailOffset, + ThumbnailOffset + ThumbnailSize); + } + + if (ThumbnailOffset <= ExifLength) { + if (ThumbnailSize > ExifLength - ThumbnailOffset) { + // If thumbnail extends past exif header, only save the part that + // actually exists. Canon's EOS viewer utility will do this - the + // thumbnail extracts ok with this hack. + ThumbnailSize = ExifLength - ThumbnailOffset; + if (ShowTags) printf("Thumbnail incorrectly placed in header\n"); + } + // The thumbnail pointer appears to be valid. Store it. + ImageInfo.ThumbnailOffset = ThumbnailOffset; + ImageInfo.ThumbnailSize = ThumbnailSize; + + if (ShowTags) { + printf("Thumbnail size: %u bytes\n", ThumbnailSize); + } + } + } +#endif +} diff --git a/toonz/sources/common/timage_io/timage_io.cpp b/toonz/sources/common/timage_io/timage_io.cpp index c9fb84c..bb2ded5 100644 --- a/toonz/sources/common/timage_io/timage_io.cpp +++ b/toonz/sources/common/timage_io/timage_io.cpp @@ -11,6 +11,7 @@ #include "trasterimage.h" #include "tiio.h" #include "tfilepath_io.h" +#include "tpixelutils.h" // boost includes #include @@ -630,6 +631,19 @@ void TImageWriter::save(const TImageP &img) { writer->open(file, info); + // add background colors for non alpha-enabled image types + if ((ras32 || ras64) && !writer->writeAlphaSupported() && + TImageWriter::getBackgroundColor() != TPixel::Black) { + if (ras32) + TRop::addBackground(ras, TImageWriter::getBackgroundColor()); + else { // ras64 + TRaster64P bgRas(ras->getSize()); + bgRas->fill(toPixel64(TImageWriter::getBackgroundColor())); + TRop::over(bgRas, ras); + ras = bgRas; + } + } + ras->lock(); if (writer->getRowOrder() == Tiio::BOTTOM2TOP) { @@ -745,6 +759,18 @@ void TImageWriter::save(const TFilePath &path, const TImageP &image) { } //=========================================================== +// Background color for saving ransparent pixel to the format not +// supporting alpha channel. Specified in the preferences. + +TPixel32 TImageWriter::m_backgroundColor; + +void TImageWriter::setBackgroundColor(TPixel32 color) { + m_backgroundColor = color; +} + +TPixel32 TImageWriter::getBackgroundColor() { return m_backgroundColor; } + +//=========================================================== // // funzioni per la registrazione dei formati (chiamate dal Plugin) // diff --git a/toonz/sources/common/tparam/tdoubleparam.cpp b/toonz/sources/common/tparam/tdoubleparam.cpp index 646f664..37c9e9f 100644 --- a/toonz/sources/common/tparam/tdoubleparam.cpp +++ b/toonz/sources/common/tparam/tdoubleparam.cpp @@ -251,7 +251,7 @@ inline double getExponentialValue(const TActualDoubleKeyframe &k0, // if bValue TEnumParam::m_declaration("intEnumParam"); @@ -94,6 +95,17 @@ void TNADoubleParam::saveData(TOStream &os) { os << getDefaultValue(); os << getValue(); } + +//========================================================= + +void TFontParam::loadData(TIStream &is) { + std::wstring str; + is >> str; + setValue(str, false); +} + +void TFontParam::saveData(TOStream &os) { os << getValue(); } + //========================================================= //========================================================= diff --git a/toonz/sources/common/trop/brush.cpp b/toonz/sources/common/trop/brush.cpp index f9b561c..28f1196 100644 --- a/toonz/sources/common/trop/brush.cpp +++ b/toonz/sources/common/trop/brush.cpp @@ -48,7 +48,7 @@ void TRop::brush(TRaster32P ras, const TPoint &aa, const TPoint &bb, int radius, const TPixel32 &col) { TPoint a = aa; TPoint b = bb; - if (a.y > b.y) tswap(a, b); // a e' piu' in basso di b + if (a.y > b.y) std::swap(a, b); // a e' piu' in basso di b int lx = ras->getLx(); int ly = ras->getLy(); diff --git a/toonz/sources/common/trop/tautoclose.cpp b/toonz/sources/common/trop/tautoclose.cpp index f14b538..7768839 100644 --- a/toonz/sources/common/trop/tautoclose.cpp +++ b/toonz/sources/common/trop/tautoclose.cpp @@ -216,8 +216,8 @@ return; int y2 = s.second.y; if (x1 > x2) { - tswap(x1, x2); - tswap(y1, y2); + std::swap(x1, x2); + std::swap(y1, y2); } buf += y1 * wrap + x1; diff --git a/toonz/sources/common/trop/traylit.cpp b/toonz/sources/common/trop/traylit.cpp index ccd3a88..7785ed1 100644 --- a/toonz/sources/common/trop/traylit.cpp +++ b/toonz/sources/common/trop/traylit.cpp @@ -329,11 +329,11 @@ void computeOctant(const TRasterPT &src, const TRasterPT &dst, int octant, dyIn = 1, dyOut = 1, y0 = tfloor(pOut.x), y1 = lxOut; if (octant == 3 || octant == 6) dyIn = -1, dyOut = -1, y0 = lxOut - tfloor(pOut.x) - 1, y1 = lxOut, - tswap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0, + std::swap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0, srcRect.x1 = lxOut - srcRect.x1; if (octant == 4 || octant == 5) dxIn = -1, dxOut = -1, x0 = lxOut - tfloor(pOut.x) - 1, x1 = lxOut, - tswap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0, + std::swap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0, srcRect.x1 = lxOut - srcRect.x1; // Horizontal octant pairs @@ -343,18 +343,18 @@ void computeOctant(const TRasterPT &src, const TRasterPT &dst, int octant, dyIn = srcWrap, dyOut = dstWrap, y0 = tfloor(pOut.y), y1 = lyOut; if (octant == 5 || octant == 8) dyIn = -srcWrap, dyOut = -dstWrap, y0 = lyOut - tfloor(pOut.y) - 1, - y1 = lyOut, tswap(srcRect.y0, srcRect.y1), srcRect.y0 = lyOut - srcRect.y0, + y1 = lyOut, std::swap(srcRect.y0, srcRect.y1), srcRect.y0 = lyOut - srcRect.y0, srcRect.y1 = lyOut - srcRect.y1; if (octant == 6 || octant == 7) dxIn = -srcWrap, dxOut = -dstWrap, x0 = lyOut - tfloor(pOut.y) - 1, - x1 = lyOut, tswap(srcRect.y0, srcRect.y1), srcRect.y0 = lyOut - srcRect.y0, + x1 = lyOut, std::swap(srcRect.y0, srcRect.y1), srcRect.y0 = lyOut - srcRect.y0, srcRect.y1 = lyOut - srcRect.y1; /*-- 縦向きのピザ領域を計算する場合は、90度回転してから --*/ // Swap x and y axis where necessary if (octant == 2 || octant == 3 || octant == 6 || octant == 7) { - tswap(lxIn, lyIn), tswap(lxOut, lyOut); - tswap(srcRect.x0, srcRect.y0), tswap(srcRect.x1, srcRect.y1); + std::swap(lxIn, lyIn), std::swap(lxOut, lyOut); + std::swap(srcRect.x0, srcRect.y0), std::swap(srcRect.x1, srcRect.y1); } int octLx = (x1 - x0), octLy = (y1 - y0); diff --git a/toonz/sources/common/trop/tresample.cpp b/toonz/sources/common/trop/tresample.cpp index 76eac86..b1fc6f3 100644 --- a/toonz/sources/common/trop/tresample.cpp +++ b/toonz/sources/common/trop/tresample.cpp @@ -3022,7 +3022,7 @@ void do_resample(TRasterCM32P rout, const TRasterCM32P &rin, else color_blob[color_blobs++] = new_color_blob; for (; j > 0 && color_blob[j].tot > color_blob[j - 1].tot; j--) - tswap(color_blob[j], color_blob[j - 1]); + std::swap(color_blob[j], color_blob[j - 1]); new_pencil_blob.val = tcm[i] & pencil_mask; new_pencil_blob.tot = (tone_mask - tone) * w[i]; for (j = 0; j < pencil_blobs; j++) @@ -3032,7 +3032,7 @@ void do_resample(TRasterCM32P rout, const TRasterCM32P &rin, else pencil_blob[pencil_blobs++] = new_pencil_blob; for (; j > 0 && pencil_blob[j].tot > pencil_blob[j - 1].tot; j--) - tswap(pencil_blob[j], pencil_blob[j - 1]); + std::swap(pencil_blob[j], pencil_blob[j - 1]); } tone = troundp(tone_tot); // if (some_pencil && (TUINT32)tone == tone_mask) @@ -3100,7 +3100,7 @@ void do_resample(TRasterCM32P rout, const TRasterCM32P &rin, color_blob[color_blobs++] = new_color_blob; // Sort the stored colors for decreasing weighted total tone for (; j > 0 && color_blob[j].tot > color_blob[j - 1].tot; j--) - tswap(color_blob[j], color_blob[j - 1]); + std::swap(color_blob[j], color_blob[j - 1]); // Deal the same way with ink colors. new_pencil_blob.val = tcm[i] & pencil_mask; @@ -3112,7 +3112,7 @@ void do_resample(TRasterCM32P rout, const TRasterCM32P &rin, else pencil_blob[pencil_blobs++] = new_pencil_blob; for (; j > 0 && pencil_blob[j].tot > pencil_blob[j - 1].tot; j--) - tswap(pencil_blob[j], pencil_blob[j - 1]); + std::swap(pencil_blob[j], pencil_blob[j - 1]); } tone = tround(tone_tot); @@ -3173,7 +3173,7 @@ void do_resample(TRasterCM32P rout, const TRasterCM32P &rin, else color_blob[color_blobs++] = new_color_blob; for (; j > 0 && color_blob[j].tot > color_blob[j - 1].tot; j--) - tswap(color_blob[j], color_blob[j - 1]); + std::swap(color_blob[j], color_blob[j - 1]); new_pencil_blob.val = tcm[i] & pencil_mask; new_pencil_blob.tot = (tone_mask - tone) * w[i]; for (j = 0; j < pencil_blobs; j++) @@ -3183,7 +3183,7 @@ void do_resample(TRasterCM32P rout, const TRasterCM32P &rin, else pencil_blob[pencil_blobs++] = new_pencil_blob; for (; j > 0 && pencil_blob[j].tot > pencil_blob[j - 1].tot; j--) - tswap(pencil_blob[j], pencil_blob[j - 1]); + std::swap(pencil_blob[j], pencil_blob[j - 1]); } tone = troundp(tone_tot); // if (some_pencil && (TUINT32)tone == tone_mask) diff --git a/toonz/sources/common/trop/trop.cpp b/toonz/sources/common/trop/trop.cpp index 9f51fad..8eb43ec 100644 --- a/toonz/sources/common/trop/trop.cpp +++ b/toonz/sources/common/trop/trop.cpp @@ -57,7 +57,7 @@ void TRop::swapRBChannels(const TRaster32P &r) { TPixel32 *pix = r->pixels(y); TPixel32 *endPix = pix + lx; while (pix < endPix) { - tswap(pix->r, pix->b); + std::swap(pix->r, pix->b); ++pix; } } diff --git a/toonz/sources/common/tsystem/tsystem.cpp b/toonz/sources/common/tsystem/tsystem.cpp index faffa21..a8b7724 100644 --- a/toonz/sources/common/tsystem/tsystem.cpp +++ b/toonz/sources/common/tsystem/tsystem.cpp @@ -32,7 +32,6 @@ using namespace std; #include #endif -#include namespace { diff --git a/toonz/sources/common/tsystem/uncpath.cpp b/toonz/sources/common/tsystem/uncpath.cpp index 0ae7e22..ca3dbca 100644 --- a/toonz/sources/common/tsystem/uncpath.cpp +++ b/toonz/sources/common/tsystem/uncpath.cpp @@ -190,12 +190,7 @@ TFilePath TSystem::toLocalPath(const TFilePath &fp) { // shi502_path e' una wstring, anche se la dichiarazione di // PSHARE_INFO_502 non lo sa! std::wstring shareLocalPathW = (LPWSTR)(p->shi502_path); - std::string shareLocalPath = ::to_string(shareLocalPathW); - //#else - // string shareLocalPath = toString(p->shi502_path); - //#endif - std::string localPath = shareLocalPath + path; - return TFilePath(localPath); + return TFilePath(shareLocalPathW) + TFilePath(path); } } diff --git a/toonz/sources/common/tunit/tunit.cpp b/toonz/sources/common/tunit/tunit.cpp index 6609619..4cde0ec 100644 --- a/toonz/sources/common/tunit/tunit.cpp +++ b/toonz/sources/common/tunit/tunit.cpp @@ -482,7 +482,16 @@ bool TMeasuredValue::setValue(std::wstring s, int *pErr) { } } if (i > j) { - value = std::stod(s.substr(j, i - j)); + try { + value = std::stod(s.substr(j, i - j)); + } + // handle exceptions + catch (const std::invalid_argument &e) { + return false; + } catch (const std::out_of_range &e) { + return false; + } + valueFlag = true; // skip blanks i = s.find_first_not_of(::to_wstring(" \t"), i); diff --git a/toonz/sources/common/tvectorimage/tregion.cpp b/toonz/sources/common/tvectorimage/tregion.cpp index 8c828b1..e287871 100644 --- a/toonz/sources/common/tvectorimage/tregion.cpp +++ b/toonz/sources/common/tvectorimage/tregion.cpp @@ -400,7 +400,7 @@ void findIntersections(double y, const TQuadratic &q, double t0, double t1, if ((rev && intersectiona < intersectionb) || (!rev && intersectiona > intersectionb)) - tswap(intersectiona, intersectionb), tswap(ta, tb); + std::swap(intersectiona, intersectionb), std::swap(ta, tb); if ((t0 < t1 && ta >= t0 && ta <= t1) || (t0 >= t1 && ta >= t1 && ta <= t0)) @@ -735,8 +735,8 @@ bool TRegion::Imp::contains(const TPointD &p) const { if (chunkIndex0 != chunkIndex1) { /*if (chunkIndex0>chunkIndex1) { -tswap(chunkIndex0, chunkIndex1); -tswap(t0, t1); +std::swap(chunkIndex0, chunkIndex1); +std::swap(t0, t1); }*/ if (chunkIndex0 > chunkIndex1) { side = findSides(p, *q0, t0, 0, leftAreOdd, side); diff --git a/toonz/sources/common/tvectorimage/tstroke.cpp b/toonz/sources/common/tvectorimage/tstroke.cpp index e495c02..f2b86a6 100644 --- a/toonz/sources/common/tvectorimage/tstroke.cpp +++ b/toonz/sources/common/tvectorimage/tstroke.cpp @@ -1071,7 +1071,7 @@ TRectD TStroke::Imp::computeSubBBox(double w0, double w1) const { const double eps = 0.000000001; int i; - if (w0 > w1) tswap(w0, w1); + if (w0 > w1) std::swap(w0, w1); double nw0 = w0 * n; double nw1 = w1 * n; @@ -1860,7 +1860,7 @@ const TThickQuadratic *TStroke::getChunk(int index) const { //----------------------------------------------------------------------------- TRectD TStroke::getBBox(double w0, double w1) const { - if (w0 > w1) tswap(w0, w1); + if (w0 > w1) std::swap(w0, w1); if (w0 != 0.0 || w1 != 1.0) return m_imp->computeSubBBox(w0, w1); diff --git a/toonz/sources/common/tvectorimage/tvectorimage.cpp b/toonz/sources/common/tvectorimage/tvectorimage.cpp index ac58b7a..d6b6fe2 100644 --- a/toonz/sources/common/tvectorimage/tvectorimage.cpp +++ b/toonz/sources/common/tvectorimage/tvectorimage.cpp @@ -2329,8 +2329,8 @@ VIStroke *TVectorImage::joinStroke(int index1, int index2, int cpIndex1, if (index1 > index2) { finalStyle = getStroke(index1)->getStyle(); - tswap(index1, index2); - tswap(cpIndex1, cpIndex2); + std::swap(index1, index2); + std::swap(cpIndex1, cpIndex2); } /* if (index1==index2) //selfLoop! diff --git a/toonz/sources/common/tvrender/tflash.cpp b/toonz/sources/common/tvrender/tflash.cpp index fcbe820..df77e14 100644 --- a/toonz/sources/common/tvrender/tflash.cpp +++ b/toonz/sources/common/tvrender/tflash.cpp @@ -147,7 +147,7 @@ public: : (p0.y < aux.p0.y)) : p0.x < aux.p0.x; } - void revert() { tswap(p0, p1); } + void revert() { std::swap(p0, p1); } }; class wChunk { diff --git a/toonz/sources/common/tvrender/tfont_qt.cpp b/toonz/sources/common/tvrender/tfont_qt.cpp index 1080fd1..96d5588 100644 --- a/toonz/sources/common/tvrender/tfont_qt.cpp +++ b/toonz/sources/common/tvrender/tfont_qt.cpp @@ -429,7 +429,8 @@ void TFontManager::getAllFamilies(vector &families) const { QStringList::const_iterator it = qFamilies.begin(); for (; it != qFamilies.end(); ++it) { - families.push_back(it->toStdWString()); + if (!m_pimpl->m_qfontdb->isPrivateFamily(*it)) + families.push_back(it->toStdWString()); } } diff --git a/toonz/sources/common/tvrender/tglregions.cpp b/toonz/sources/common/tvrender/tglregions.cpp index f698d84..8ae9139 100644 --- a/toonz/sources/common/tvrender/tglregions.cpp +++ b/toonz/sources/common/tvrender/tglregions.cpp @@ -146,10 +146,13 @@ void drawArrows(TStroke *stroke, bool onlyFirstPoint) { for (int i = 0; i <= points; i++) { currentPosition = i / (double)points; point = stroke->getPointAtLength(length * currentPosition); - prePoint = (i == 0) ? point : stroke->getPointAtLength( - length * (currentPosition - 0.02)); - postPoint = (i == points) ? point : stroke->getPointAtLength( - length * (currentPosition + 0.02)); + prePoint = + (i == 0) ? point + : stroke->getPointAtLength(length * (currentPosition - 0.02)); + postPoint = + (i == points) + ? point + : stroke->getPointAtLength(length * (currentPosition + 0.02)); if (prePoint == postPoint) continue; @@ -565,7 +568,7 @@ static void tglDoDraw(const TVectorRenderData &rd, TRegion *r) { //------------------------------------------------------------------------------------ -static void tglDoDraw(const TVectorRenderData &rd, const TStroke *s) { +static bool tglDoDraw(const TVectorRenderData &rd, const TStroke *s) { bool visible = false; int colorCount = 0; @@ -587,6 +590,8 @@ static void tglDoDraw(const TVectorRenderData &rd, const TStroke *s) { } } + bool ret = false; + if (visible) { // Change stroke color to blue if guided drawing if (rd.m_showGuidedDrawing && rd.m_highLightNow) { @@ -596,6 +601,7 @@ static void tglDoDraw(const TVectorRenderData &rd, const TStroke *s) { delete newRd; TStroke *new_s = (TStroke *)s; drawFirstControlPoint(rd, new_s); + ret = rd.m_animatedGuidedDrawing; } else { tglDraw(rd, s, false); } @@ -604,6 +610,7 @@ static void tglDoDraw(const TVectorRenderData &rd, const TStroke *s) { // drawControlPoints(rd, vim->getStroke(i), sqrt(tglGetPixelSize2()), true); // assert(checkQuadraticDistance(vim->getStroke(i),true)); #endif + return ret; } //------------------------------------------------------------------------------------ @@ -611,7 +618,7 @@ static void tglDoDraw(const TVectorRenderData &rd, const TStroke *s) { namespace { void doDraw(const TVectorImage *vim, const TVectorRenderData &_rd, - bool drawEnteredGroup) { + bool drawEnteredGroup, TStroke **guidedStroke = 0) { static TOnionFader *fade = new TOnionFader(TPixel::White, 0.5); TVectorRenderData rd(_rd); @@ -663,7 +670,8 @@ rdRegions.m_alphaChannel = rdRegions.m_antiAliasing = false;*/ CurrStrokeIndex = strokeIndex; CurrVimg = vim; #endif - tglDoDraw(rd, vim->getStroke(strokeIndex)); + bool isGuided = tglDoDraw(rd, vim->getStroke(strokeIndex)); + if (isGuided && guidedStroke) *guidedStroke = vim->getStroke(strokeIndex); strokeIndex++; } } @@ -672,7 +680,8 @@ rdRegions.m_alphaChannel = rdRegions.m_antiAliasing = false;*/ //------------------------------------------------------------------------------------ -void tglDraw(const TVectorRenderData &rd, const TVectorImage *vim) { +void tglDraw(const TVectorRenderData &rd, const TVectorImage *vim, + TStroke **guidedStroke) { assert(vim); if (!vim) return; @@ -689,8 +698,9 @@ void tglDraw(const TVectorRenderData &rd, const TVectorImage *vim) { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0); - doDraw(vim, rd, false); - if (!rd.m_isIcon && vim->isInsideGroup() > 0) doDraw(vim, rd, true); + doDraw(vim, rd, false, guidedStroke); + if (!rd.m_isIcon && vim->isInsideGroup() > 0) + doDraw(vim, rd, true, guidedStroke); glDisable(GL_ALPHA_TEST); diff --git a/toonz/sources/common/tvrender/tsimplecolorstyles.cpp b/toonz/sources/common/tvrender/tsimplecolorstyles.cpp index bbff67c..1ff6270 100644 --- a/toonz/sources/common/tvrender/tsimplecolorstyles.cpp +++ b/toonz/sources/common/tvrender/tsimplecolorstyles.cpp @@ -1,4 +1,5 @@ +#include // TnzCore includes #include "tsystem.h" @@ -91,19 +92,223 @@ TRaster32P makeTexture(const TRaster32P &ras) { //----------------------------------------------------------------------------- -void drawAntialiasedOutline(const std::vector &_v, - const TStroke *stroke) { - static const int stride = 2 * sizeof(TOutlinePoint); +class OutlineBuilder { +private: + double width; + int stage; + double stages[3][3]; + double px, py, pz; + double ax, ay; + + inline void next_stage(const double &x, const double &y, const double &z) + { stages[stage][0] = x; stages[stage][1] = y; stages[stage][2] = z; ++stage; } + +public: + std::vector vertices; + + explicit OutlineBuilder(double width, int count = 0): + width(width), stage(0), px(), py(), pz(), ax(), ay() + { + memset(stages, 0, sizeof(stages)); + vertices.reserve(12*(count + 2)); + } + + void add(double x, double y, double z = 0.0) { + const double maxl = 4.0; + + if (stage == 0) next_stage(x, y, z); else { + double bx = x - px; + double by = y - py; + double lb = sqrt(bx*bx + by*by); + if (lb < 1e-9) + return; + bx = width*bx/lb; + by = width*by/lb; + + if (stage == 1) next_stage(x, y, z); else { + if (stage == 2) next_stage(x, y, z); + double l = fabs(ax + bx) > 1e-9 ? -(ay - by)/(ax + bx) + : fabs(ay + by) > 1e-9 ? (ax - bx)/(ay + by) + : 0.0; + if (fabs(l) > maxl || fabs(l) < 1.0 || l > 0.0) { + vertices.resize(vertices.size() + 12); + double *p = &vertices.back() - 11; + p[ 0] = px; + p[ 1] = py; + p[ 2] = pz; + p[ 3] = px + ay; + p[ 4] = py - ax; + p[ 5] = pz; + p[ 6] = px; + p[ 7] = py; + p[ 8] = pz; + p[ 9] = px + by; + p[10] = py - bx; + p[11] = pz; + } else { + vertices.resize(vertices.size() + 6); + double *p = &vertices.back() - 5; + p[0] = px; + p[1] = py; + p[2] = pz; + p[3] = px - l*bx + by; + p[4] = py - l*by - bx; + p[5] = pz; + } + } + + ax = bx; ay = by; + } + + px = x; py = y; pz = z; + } + + void finish() { + for(int i = 0; i < stage; ++i) + add(stages[i][0], stages[i][1], stages[i][2]); + stage = 0; + } + + double get_width() const + { return width; } + + void restart(double width) { + this->width = width; + stage = 0; + vertices.clear(); + } + + void invert() + { restart(-width); } +}; - glEnableClientState(GL_VERTEX_ARRAY); +void vector4_div(double *v) { + double k = fabs(v[3]) > 1e-9 ? 1.0/v[3] : 0.0; + v[0] *= k, v[1] *= k, v[2] *= k; v[3] = 1.0; +} + +void matrix4_x_vector4(double *dv, const double *m, const double *v) { + dv[0] = m[0]*v[0] + m[4]*v[1] + m[ 8]*v[2] + m[12]*v[3]; + dv[1] = m[1]*v[0] + m[5]*v[1] + m[ 9]*v[2] + m[13]*v[3]; + dv[2] = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3]; + dv[3] = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3]; +} - glVertexPointer(2, GL_DOUBLE, stride, &_v[0]); - glDrawArrays(GL_LINE_STRIP, 0, _v.size() / 2); +void matrix4_x_matrix4(double *dm, const double *ma, const double *mb) { + matrix4_x_vector4(dm + 0, ma, mb + 0); + matrix4_x_vector4(dm + 4, ma, mb + 4); + matrix4_x_vector4(dm + 8, ma, mb + 8); + matrix4_x_vector4(dm + 12, ma, mb + 12); +} + +class AntialiasingOutlinePainter: public OutlineBuilder { +private: + double matrix[16]; + double projection_matrix[16]; + double modelview_matrix[16]; + double anti_viewport_matrix[16]; - glVertexPointer(2, GL_DOUBLE, stride, &_v[1]); - glDrawArrays(GL_LINE_STRIP, 0, _v.size() / 2); +public: + explicit AntialiasingOutlinePainter(int count = 0): + OutlineBuilder(1.0, 0) + { + memset(matrix, 0, sizeof(matrix)); + memset(projection_matrix, 0, sizeof(projection_matrix)); + memset(modelview_matrix, 0, sizeof(modelview_matrix)); + memset(anti_viewport_matrix, 0, sizeof(anti_viewport_matrix)); + + // read transformations + double viewport[4] = {}; + glGetDoublev(GL_VIEWPORT, viewport); + glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix); + glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix); + + double viewport_matrix[16] = {}; + viewport_matrix[ 0] = 0.5*viewport[2]; + viewport_matrix[ 5] = 0.5*viewport[3]; + viewport_matrix[10] = 1.0; + viewport_matrix[12] = 0.5*viewport[2]; + viewport_matrix[13] = 0.5*viewport[3]; + viewport_matrix[15] = 1.0; + + anti_viewport_matrix[ 0] = 2.0/viewport[2]; + anti_viewport_matrix[ 5] = 2.0/viewport[3]; + anti_viewport_matrix[10] = 1.0; + anti_viewport_matrix[12] = -1.0; + anti_viewport_matrix[13] = -1.0; + anti_viewport_matrix[15] = 1.0; + + { double tmp[16] = {}; + matrix4_x_matrix4(tmp, projection_matrix, modelview_matrix); + matrix4_x_matrix4(matrix, viewport_matrix, tmp); } + } + + void add(double x, double y, double z = 0.0) { + double dest[4], src[4] = {x, y, z, 1.0}; + matrix4_x_vector4(dest, matrix, src); + vector4_div(dest); + OutlineBuilder::add(dest[0], dest[1], dest[2]); + } + + void finish() { + OutlineBuilder::finish(); + if (vertices.empty()) + return; + int count = (int)vertices.size()/6; + + // prepare colors + float color[8] = {}; + glGetFloatv(GL_CURRENT_COLOR, color); + memcpy(color+4, color, 3*sizeof(float)); + std::vector colors(8*count); + for(float *c = &colors[0], *ce = &colors.back(); c < ce; c += 8) + memcpy(c, color, sizeof(color)); + + // draw + glMatrixMode(GL_MODELVIEW); + glLoadMatrixd(anti_viewport_matrix); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_DOUBLE, 0, &vertices.front()); + glColorPointer(4, GL_FLOAT, 0, &colors.front()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*count); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glLoadMatrixd(projection_matrix); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixd(modelview_matrix); + + glColor4fv(color); + restart(get_width()); + } +}; + +void drawAntialiasedOutline( + const std::vector &_v, const TStroke *stroke ) +{ + if (_v.empty()) + return; - glDisableClientState(GL_VERTEX_ARRAY); + const TOutlinePoint *begin = &_v.front(), *end = &_v.back(); + assert(_v.size() % 2 == 0); + + AntialiasingOutlinePainter outline(_v.size()); + for(const TOutlinePoint *i = begin; i < end; i += 2) + outline.add(i->x, i->y); + for(const TOutlinePoint *i = end; i > begin; i -= 2) + outline.add(i->x, i->y); + outline.finish(); + + outline.invert(); + for(const TOutlinePoint *i = begin; i < end; i += 2) + outline.add(i->x, i->y); + for(const TOutlinePoint *i = end; i > begin; i -= 2) + outline.add(i->x, i->y); + outline.finish(); } } // namespace diff --git a/toonz/sources/image/avi/tiio_avi.cpp b/toonz/sources/image/avi/tiio_avi.cpp index 0f7825f..121079f 100644 --- a/toonz/sources/image/avi/tiio_avi.cpp +++ b/toonz/sources/image/avi/tiio_avi.cpp @@ -544,9 +544,6 @@ void TLevelWriterAvi::doSaveSoundTrack() { WAVEFORMATEX waveinfo; int ret; LONG lSampWritten, lBytesWritten; - int rc; - - rc = FALSE; AVISTREAMINFO audioStreamInfo; memset(&audioStreamInfo, 0, sizeof(AVISTREAMINFO)); diff --git a/toonz/sources/image/pli/tiio_pli.cpp b/toonz/sources/image/pli/tiio_pli.cpp index df0dcb5..4878a1d 100644 --- a/toonz/sources/image/pli/tiio_pli.cpp +++ b/toonz/sources/image/pli/tiio_pli.cpp @@ -457,6 +457,7 @@ TImageWriterPli::TImageWriterPli(const TFilePath &f, const TFrameId &frameId, static void putStroke(TStroke *stroke, int &currStyleId, std::vector &tags) { double maxThickness = 0; + bool nonStdOutline = false; assert(stroke); int chunkCount = stroke->getChunkCount(); @@ -477,10 +478,12 @@ static void putStroke(TStroke *stroke, int &currStyleId, // If the outline options are non-standard (not round), add the outline infos TStroke::OutlineOptions &options = stroke->outlineOptions(); if (options.m_capStyle != TStroke::OutlineOptions::ROUND_CAP || - options.m_joinStyle != TStroke::OutlineOptions::ROUND_JOIN) { + options.m_joinStyle != TStroke::OutlineOptions::ROUND_JOIN || + options.m_miterLower != 0.0 || options.m_miterUpper != 4.0) { StrokeOutlineOptionsTag *outlineOptionsTag = new StrokeOutlineOptionsTag(options); tags.push_back((PliObjectTag *)outlineOptionsTag); + nonStdOutline = true; } UINT k; @@ -501,6 +504,14 @@ static void putStroke(TStroke *stroke, int &currStyleId, tags.push_back((PliObjectTag *)quadChainTag); // pli->addTag(groupTag[count++]); + + if (nonStdOutline) { + // Restore default outline settings + TStroke::OutlineOptions resetoptions; + StrokeOutlineOptionsTag *outlineOptionsTag = + new StrokeOutlineOptionsTag(resetoptions); + tags.push_back((PliObjectTag *)outlineOptionsTag); + } } //----------------------------------------------------------------------------- diff --git a/toonz/sources/image/png/tiio_png.cpp b/toonz/sources/image/png/tiio_png.cpp index 5b44efe..0ae4f7b 100644 --- a/toonz/sources/image/png/tiio_png.cpp +++ b/toonz/sources/image/png/tiio_png.cpp @@ -760,6 +760,8 @@ public: void flush() override; bool write64bitSupported() const override { return true; } + // m_matte is set to "Alpha Channel" property value in the function open() + bool writeAlphaSupported() const override { return m_matte; }; }; //--------------------------------------------------------- diff --git a/toonz/sources/image/sgi/filesgi.cpp b/toonz/sources/image/sgi/filesgi.cpp index a5638f8..9542f19 100644 --- a/toonz/sources/image/sgi/filesgi.cpp +++ b/toonz/sources/image/sgi/filesgi.cpp @@ -1075,6 +1075,12 @@ public: void setProperties(TPropertyGroup *properties); + // m_header->zsize is updated with "Bits Per Pixel" property value in the + // function open() + bool writeAlphaSupported() const override { + return m_header && (m_header->zsize == 4); + } + private: // not implemented SgiWriter(const SgiWriter &); diff --git a/toonz/sources/image/svg/tiio_svg.cpp b/toonz/sources/image/svg/tiio_svg.cpp index 7b2b5e2..d527385 100644 --- a/toonz/sources/image/svg/tiio_svg.cpp +++ b/toonz/sources/image/svg/tiio_svg.cpp @@ -1285,7 +1285,7 @@ void nsvg__pathArcTo(struct NSVGParser *p, float *cpx, float *cpy, float *args, t[5] = cy; // Split arc into max 90 degree segments. - ndivs = (int)(fabsf(da) / (NSVG_PI * 0.5f) + 0.5f); + ndivs = (int)(ceil(fabsf(da)) / (NSVG_PI * 0.5f) + 0.5f); hda = (da / (float)ndivs) / 2.0f; kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda)); if (da < 0.0f) kappa = -kappa; @@ -1320,6 +1320,8 @@ void nsvg__parsePath(struct NSVGParser *p, const char **attr) { char closedFlag; int i; char item[64]; + float prev_m_cpx, prev_m_cpy; + bool prev_m_exists; for (i = 0; attr[i]; i += 2) { if (strcmp(attr[i], "d") == 0) { @@ -1330,6 +1332,7 @@ void nsvg__parsePath(struct NSVGParser *p, const char **attr) { cpy = 0; closedFlag = 0; nargs = 0; + prev_m_exists = false; while (*s) { s = nsvg__getNextPathItem(s, item); @@ -1340,7 +1343,19 @@ void nsvg__parsePath(struct NSVGParser *p, const char **attr) { switch (cmd) { case 'm': case 'M': + + // If moveto is relative it relative to previous moveto point + if (cmd == 'm' && prev_m_exists) { + cpx = prev_m_cpx; + cpy = prev_m_cpy; + } + nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0); + + prev_m_cpx = cpx; + prev_m_cpy = cpy; + prev_m_exists = true; + // Moveto can be followed by multiple coordinate pairs, // which should be treated as linetos. cmd = (cmd == 'm') ? 'l' : 'L'; @@ -2073,6 +2088,15 @@ TStroke *buildStroke(NSVGpath *path, float width) { s->setSelfLoop(path->closed); + std::vector tpoints; + s->getControlPoints(tpoints); + + for (int j = 0; j < tpoints.size(); j++) { + tpoints[j].thick = width; + } + + s->reshape(&tpoints[0], tpoints.size()); + return s; } diff --git a/toonz/sources/image/tga/tiio_tga.cpp b/toonz/sources/image/tga/tiio_tga.cpp index 07810f7..8eaadc2 100644 --- a/toonz/sources/image/tga/tiio_tga.cpp +++ b/toonz/sources/image/tga/tiio_tga.cpp @@ -609,6 +609,12 @@ public: void writeLine32rle(char *buffer); void writeLine(char *buffer) override { (this->*m_writeLineProc)(buffer); } + + // m_header.ImagePixelSize is set to "Bits Per Pixel" property value + // in the function open() + bool writeAlphaSupported() const override { + return m_header.ImagePixelSize == 32; + } }; //------------------------------------------------------------ diff --git a/toonz/sources/image/tif/tiio_tif.cpp b/toonz/sources/image/tif/tiio_tif.cpp index 0c65df3..f8cec50 100644 --- a/toonz/sources/image/tif/tiio_tif.cpp +++ b/toonz/sources/image/tif/tiio_tif.cpp @@ -230,8 +230,8 @@ break;*/ bool swapxy = false; // orient == ORIENTATION_RIGHTTOP; if (swapxy) { - tswap(w, h); - tswap(xdpi, ydpi); + std::swap(w, h); + std::swap(xdpi, ydpi); } m_xdpi = xdpi; @@ -399,8 +399,8 @@ if(stripSize>0) m_info.m_y0 = 0; } if (swapxy) { - tswap(m_info.m_x0, m_info.m_y0); - tswap(m_info.m_lx, m_info.m_ly); + std::swap(m_info.m_x0, m_info.m_y0); + std::swap(m_info.m_lx, m_info.m_ly); } m_info.m_x1 = m_info.m_x0 + w; m_info.m_y1 = m_info.m_y0 + h; @@ -770,6 +770,11 @@ public: void flush() override; Tiio::RowOrder getRowOrder() const override { return m_rowOrder; } + + // m_bpp is set to "Bits Per Pixel" property value in the function open() + bool writeAlphaSupported() const override { + return (m_bpp == 32 || m_bpp == 64); + } }; //------------------------------------------------------------ diff --git a/toonz/sources/image/tzl/tiio_tzl.cpp b/toonz/sources/image/tzl/tiio_tzl.cpp index bd69682..c94d9eb 100644 --- a/toonz/sources/image/tzl/tiio_tzl.cpp +++ b/toonz/sources/image/tzl/tiio_tzl.cpp @@ -1409,8 +1409,15 @@ void TLevelReaderTzl::readPalette() { TPalette *palette = 0; if (is && fs.doesExist()) { - is >> p; - palette = dynamic_cast(p); + std::string tagName; + if (is.matchTag(tagName) && tagName == "palette") { + std::string gname; + is.getTagParam("name", gname); + palette = new TPalette(); + palette->loadData(is); + palette->setGlobalName(::to_wstring(gname)); + is.matchEndTag(); + } } if (!palette) { diff --git a/toonz/sources/include/orientation.h b/toonz/sources/include/orientation.h index 05b934e..58584cd 100644 --- a/toonz/sources/include/orientation.h +++ b/toonz/sources/include/orientation.h @@ -118,7 +118,13 @@ enum class PredefinedRect { ZOOM_OUT_AREA, ZOOM_OUT, LAYER_FOOTER_PANEL, - PREVIEW_FRAME_AREA + PREVIEW_FRAME_AREA, + SHIFTTRACE_DOT, + SHIFTTRACE_DOT_AREA, + PANEL_EYE, + PANEL_PREVIEW_LAYER, + PANEL_LOCK, + PANEL_LAYER_NAME }; enum class PredefinedLine { LOCKED, //! dotted vertical line when cell is locked diff --git a/toonz/sources/include/tcg/hpp/image_ops.hpp b/toonz/sources/include/tcg/hpp/image_ops.hpp index 38ae9c6..ef95bc2 100644 --- a/toonz/sources/include/tcg/hpp/image_ops.hpp +++ b/toonz/sources/include/tcg/hpp/image_ops.hpp @@ -6,7 +6,6 @@ // tcg includes #include "../image_ops.h" #include "../pixel.h" -#include "../unique_ptr.h" // STD includes #include @@ -177,7 +176,7 @@ void blurRows(const ImgIn &imgIn, ImgOut &imgOut, int radius, Scalar) { outWrap = image_traits::wrap(imgOut); // Allocate an intermediate line of pixels to store sum values - tcg::unique_ptr sums(new PixSum[inLx]); + std::unique_ptr sums(new PixSum[inLx]); // Filter rows for (int y = 0; y != inLy; ++y) { @@ -210,8 +209,8 @@ void blurRows(const ImgIn &imgIn, ImgOut &imgOut, int radius, outWrap = image_traits::wrap(imgOut); // Allocate an intermediate line of pixels to store sum values - tcg::unique_ptr sums(new PixSum[inLx]); - tcg::unique_ptr counts(new int[inLx]); + std::unique_ptr sums(new PixSum[inLx]); + std::unique_ptr counts(new int[inLx]); // Filter rows for (int y = 0; y != inLy; ++y) { @@ -244,7 +243,7 @@ void blurCols(const ImgIn &imgIn, ImgOut &imgOut, int radius, Scalar) { outWrap = image_traits::wrap(imgOut); // Allocate an intermediate line of pixels to store sum values - tcg::unique_ptr sums(new PixSum[inLy]); + std::unique_ptr sums(new PixSum[inLy]); // Filter columns for (int x = 0; x != inLx; ++x) { @@ -278,8 +277,8 @@ void blurCols(const ImgIn &imgIn, ImgOut &imgOut, int radius, outWrap = image_traits::wrap(imgOut); // Allocate an intermediate line of pixels to store sum values - tcg::unique_ptr sums(new PixSum[inLy]); - tcg::unique_ptr counts(new int[inLy]); + std::unique_ptr sums(new PixSum[inLy]); + std::unique_ptr counts(new int[inLy]); // Filter columns for (int x = 0; x != inLx; ++x) { diff --git a/toonz/sources/include/tcg/tcg_unique_ptr.h b/toonz/sources/include/tcg/tcg_unique_ptr.h deleted file mode 100644 index 1abc7c1..0000000 --- a/toonz/sources/include/tcg/tcg_unique_ptr.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#include "unique_ptr.h" diff --git a/toonz/sources/include/tcg/unique_ptr.h b/toonz/sources/include/tcg/unique_ptr.h deleted file mode 100644 index 6b5fb79..0000000 --- a/toonz/sources/include/tcg/unique_ptr.h +++ /dev/null @@ -1,122 +0,0 @@ -#pragma once - -#ifndef TCG_UNIQUE_PTR_H -#define TCG_UNIQUE_PTR_H - -// tcg includes -#include "traits.h" -#include "base.h" -#include "deleter_types.h" - -// STD includes -#include "assert.h" -#include - -namespace tcg { - -//********************************************************************************** -// unique_ptr definition -//********************************************************************************** - -/*! - \brief The unique_ptr class is a C++03 compatibility class that implements - a \a noncopyable smart pointer, similarly to \p boost::scoped_ptr, - but accepting a custom deleter type as template parameter. - - \details \par Properties - This class provides the following features: -
    -
  • It's noncopyable, like \p boost::scoped_ptr.
  • -
  • Unlike \p boost::scoped_ptr, it provides the release() -method.
  • -
  • Arrays are valid template types - so tcg::unique_ptr - is accepted and works as expected.
  • -
  • Like \p std::unique_ptr, it accepts custom \a inheritable -deallocators.
  • -
- \par Incomplete types - Like \p boost::scoped_ptr, incomplete types are accepted as template - parameter, \a provided their definition is completed by the time the -destructor - is invoked. In particular, pointers to incomplete types \b must be -stored in - classes whose destructor is defined in an implementation file - and -remember - that compiler-generated destructors are always implicitly -inlined. - - \par Type erasure - Unlike shared_ptr, this class does not employ type erasure - on the deleter object - which is an explicit template argument by - default. This means that the pointed object type must be \b complete - at the moment the \p unique_ptr is destroyed, \a except if the - supplied deleter is type-erased on its own. - - \remark The C++11 class \p std::unique_ptr should be preferred, if possible. -*/ - -template > -class unique_ptr : private D // Empty Base Optimization -{ -public: - typedef typename tcg::traits::element_type element_type; - typedef typename tcg::traits::pointer_type ptr_type; - typedef typename tcg::traits::reference_type ref_type; - -public: - explicit unique_ptr(ptr_type ptr = ptr_type()) // Explicit unary constructors - : m_ptr(ptr) {} - explicit unique_ptr(D d) : m_ptr(), D(d) {} // - unique_ptr(ptr_type ptr, D d) : m_ptr(ptr), D(d) {} - - ~unique_ptr() { D::operator()(m_ptr); } - - friend void swap(unique_ptr &a, unique_ptr &b) { - using std::swap; - - swap(static_cast(a), static_cast(b)); - swap(a.m_ptr, b.m_ptr); - } - - // Explicitly disabled (safe) conversion to bool - although - // std::unique_ptr could support it, that would just add overhead. - // It's also not compatible with other C++03 smart pointers. - - // typedef ptr_type unique_ptr::* bool_type; - - // operator bool_type() const // Safe bool - // idiom - // { return m_ptr ? &unique_ptr::m_ptr : 0; } // additional - // branching! - - ptr_type operator->() const { return m_ptr; } - ref_type operator*() const { return *m_ptr; } - ref_type operator[](size_t idx) const { return m_ptr[idx]; } - - void reset(ptr_type ptr = ptr_type()) { - D::operator()(m_ptr); - m_ptr = ptr; - } - - void reset(ptr_type ptr, D d) { - reset(ptr); - D::operator=(d); - } - - ptr_type release() { - ptr_type ptr = m_ptr; - m_ptr = ptr_type(); - return ptr; - } - - const ptr_type get() const { return m_ptr; } - ptr_type get() { return m_ptr; } - -private: - ptr_type m_ptr; -}; - -} // namespace tcg - -#endif // TCG_UNIQUE_PTR_H diff --git a/toonz/sources/include/tcommon.h b/toonz/sources/include/tcommon.h index 5d27757..a5dec3d 100644 --- a/toonz/sources/include/tcommon.h +++ b/toonz/sources/include/tcommon.h @@ -28,6 +28,7 @@ #include #include #include +#include #if 0 && defined(__GNUC__) // typedef seems strong on GCC and breaks code with TException.. @@ -89,12 +90,6 @@ typedef unsigned char BYTE; #endif template -inline void tswap(T &a, T &b) { - T tmp = a; - a = b; - b = tmp; -} -template inline T tcrop(T x, T a, T b) { return std::min(std::max(x, a), b); } @@ -181,7 +176,6 @@ inline std::ostream &operator<<(std::ostream &out, const std::string &s) { #define tArrayCount(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0])) -const std::string mySettingsFileName = "mysettings.ini"; const std::string styleNameEasyInputWordsFileName = "stylename_easyinput.ini"; #endif //__T_COMMON_INCLUDED diff --git a/toonz/sources/include/tenv.h b/toonz/sources/include/tenv.h index 155044c..dc793e1 100644 --- a/toonz/sources/include/tenv.h +++ b/toonz/sources/include/tenv.h @@ -89,8 +89,6 @@ public: // // es.: TEnv::setApplication("Toonz","5.0"); // -DVAPI void setApplication(std::string applicationName, std::string version, - std::string revision = std::string()); DVAPI std::string getApplicationName(); DVAPI std::string getApplicationVersion(); @@ -137,9 +135,6 @@ DVAPI TFilePath getConfigDir(); // bisogna chiamare TEnv::setStuffDir(stuffdir) prima di ogni altra operazione DVAPI void setStuffDir(const TFilePath &stuffDir); -DVAPI TFilePath getDllRelativeDir(); -DVAPI void setDllRelativeDir(const TFilePath &dllRelativeDir); - DVAPI void saveAllEnvVariables(); // register command line argument paths. diff --git a/toonz/sources/include/tfilepath.h b/toonz/sources/include/tfilepath.h index b71f727..3004db6 100644 --- a/toonz/sources/include/tfilepath.h +++ b/toonz/sources/include/tfilepath.h @@ -76,8 +76,10 @@ public: const TFrameId &operator--(); TFrameId &operator=(const TFrameId &f) { - m_frame = f.m_frame; - m_letter = f.m_letter; + m_frame = f.m_frame; + m_letter = f.m_letter; + m_zeroPadding = f.m_zeroPadding; + m_startSeqInd = f.m_startSeqInd; return *this; } diff --git a/toonz/sources/include/tiio.h b/toonz/sources/include/tiio.h index b8e655c..e2bb7a2 100644 --- a/toonz/sources/include/tiio.h +++ b/toonz/sources/include/tiio.h @@ -106,6 +106,7 @@ public: virtual RowOrder getRowOrder() const { return BOTTOM2TOP; } virtual bool write64bitSupported() const { return false; } + virtual bool writeAlphaSupported() const { return true; } void setProperties(TPropertyGroup *properties); diff --git a/toonz/sources/include/tiio_jpg_exif.h b/toonz/sources/include/tiio_jpg_exif.h new file mode 100644 index 0000000..1d619d8 --- /dev/null +++ b/toonz/sources/include/tiio_jpg_exif.h @@ -0,0 +1,139 @@ +/*------------------------------------------------------------- +tiio_jpg_exif.h +Based on source code of a public domain software "Exif Jpeg header manipulation +tool (jhead)" by Matthias Wandel. +For now it is used only for obtaining resolution values. +http://www.sentex.net/~mwandel/jhead/ +-------------------------------------------------------------*/ +#pragma once +#ifndef TIIO_JPG_EXIF_H +#define TIIO_JPG_EXIF_H + +#include + +// undefining ReadAllTags will load only resolution infomation +#define ReadAllTags +#undef ReadAllTags + +#define MAX_COMMENT_SIZE 16000 +#define MAX_DATE_COPIES 10 + +#ifdef _WIN32 +#define PATH_MAX _MAX_PATH +#define SLASH '\\' +#else +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif +#define SLASH '/' +#endif + +class JpgExifReader { + enum FORMATS { + FMT_BYTE = 1, + FMT_STRING, + FMT_USHORT, + FMT_ULONG, + FMT_URATIONAL, + FMT_SBYTE, + FMT_UNDEFINED, + FMT_SSHORT, + FMT_SLONG, + FMT_SRATIONAL, + FMT_SINGLE, + FMT_DOUBLE + }; + + int NUM_FORMATS = FMT_DOUBLE; + + struct ExifImageInfo { + float xResolution = 0.0; + float yResolution = 0.0; + int ResolutionUnit; +#ifdef ReadAllTags + char FileName[PATH_MAX + 1]; + time_t FileDateTime; + + unsigned FileSize; + char CameraMake[32]; + char CameraModel[40]; + char DateTime[20]; + unsigned Height, Width; + int Orientation; + int IsColor; + int Process; + int FlashUsed; + float FocalLength; + float ExposureTime; + float ApertureFNumber; + float Distance; + float CCDWidth; + float ExposureBias; + float DigitalZoomRatio; + int FocalLength35mmEquiv; // Exif 2.2 tag - usually not present. + int Whitebalance; + int MeteringMode; + int ExposureProgram; + int ExposureMode; + int ISOequivalent; + int LightSource; + int DistanceRange; + + char Comments[MAX_COMMENT_SIZE]; + int CommentWidthchars; // If nonzero, widechar comment, indicates number of + // chars. + + unsigned ThumbnailOffset; // Exif offset to thumbnail + unsigned ThumbnailSize; // Size of thumbnail. + unsigned LargestExifOffset; // Last exif data referenced (to check if + // thumbnail is at end) + + char ThumbnailAtEnd; // Exif header ends with the thumbnail + // (we can only modify the thumbnail if its at the end) + int ThumbnailSizeOffset; + + int DateTimeOffsets[MAX_DATE_COPIES]; + int numDateTimeTags = 0; + + int GpsInfoPresent; + char GpsLat[31]; + char GpsLong[31]; + char GpsAlt[20]; + + int QualityGuess; +#endif + } ImageInfo; + +#ifdef ReadAllTags + unsigned char* DirWithThumbnailPtrs; + double FocalplaneXRes; + double FocalplaneUnits; + int ExifImageWidth; + + // for fixing the rotation. + void* OrientationPtr[2]; + int OrientationNumFormat[2]; + int NumOrientations = 0; +#endif + + int MotorolaOrder = 0; + + int Get16u(void* Short); + unsigned Get32u(void* Long); + int Get32s(void* Long); + void PrintFormatNumber(void* ValuePtr, int Format, int ByteCount); + double ConvertAnyFormat(void* ValuePtr, int Format); + +public: + void process_EXIF(unsigned char* ExifSection, unsigned int length); + void ProcessExifDir(unsigned char* DirStart, unsigned char* OffsetBase, + unsigned ExifLength, int NestingLevel); + + // obtaining resolution info + bool containsResolution() { return ImageInfo.xResolution != 0.0; } + float getXResolution() { return ImageInfo.xResolution; } + float getYResolution() { return ImageInfo.yResolution; } + int getResolutionUnit() { return ImageInfo.ResolutionUnit; } +}; + +#endif \ No newline at end of file diff --git a/toonz/sources/include/timage_io.h b/toonz/sources/include/timage_io.h index d6b99d0..07fecf3 100644 --- a/toonz/sources/include/timage_io.h +++ b/toonz/sources/include/timage_io.h @@ -205,6 +205,10 @@ typedef TImageWriter *TImageWriterCreateProc(const TFilePath &path); class DVAPI TImageWriter : public TSmartObject { DECLARE_CLASS_CODE + // Background color for saving transparent pixel to the format not + // supporting alpha channel. Specified in the preferences. + static TPixel32 m_backgroundColor; + protected: // std::fstream m_stream; TFilePath m_path; @@ -237,6 +241,9 @@ public: static void define(QString extension, TImageWriterCreateProc *proc, bool isRenderFormat); + + static void setBackgroundColor(TPixel32 color); + static TPixel32 getBackgroundColor(); }; //----------------------------------------------------------- diff --git a/toonz/sources/include/tnotanimatableparam.h b/toonz/sources/include/tnotanimatableparam.h index b28497d..d61f07b 100644 --- a/toonz/sources/include/tnotanimatableparam.h +++ b/toonz/sources/include/tnotanimatableparam.h @@ -13,6 +13,7 @@ #include "tconvert.h" #include +#include #undef DVAPI #undef DVVAR @@ -169,6 +170,7 @@ public: using namespace std; return to_string(getValue()); } + bool hasKeyframes() const override { return 0; }; void getKeyframes(std::set &) const override{}; int getNextKeyframe(double) const override { return -1; }; @@ -280,6 +282,8 @@ template class DVAPI TPersistDeclarationT; class DVAPI TStringParam final : public TNotAnimatableParam { PERSIST_DECLARATION(TStringParam); + bool m_multiLine = false; + public: TStringParam(std::wstring v = L"") : TNotAnimatableParam(v) {} TStringParam(const TStringParam &src) @@ -287,6 +291,9 @@ public: TParam *clone() const override { return new TStringParam(*this); } void loadData(TIStream &is) override; void saveData(TOStream &os) override; + + void setMultiLineEnabled(bool enable) { m_multiLine = enable; } + bool isMultiLineEnabled() { return m_multiLine; } }; DEFINE_PARAM_SMARTPOINTER(TStringParam, std::wstring) @@ -393,6 +400,32 @@ private: DEFINE_PARAM_SMARTPOINTER(TNADoubleParam, double) +//========================================================= +// +// class TFontParam +// +//========================================================= + +#ifdef _WIN32 +template class DVAPI TNotAnimatableParam; +class TFontParam; +template class DVAPI TPersistDeclarationT; +#endif + +class DVAPI TFontParam final : public TNotAnimatableParam { + PERSIST_DECLARATION(TFontParam); + +public: + TFontParam(std::wstring v = QFont().toString().toStdWString()) + : TNotAnimatableParam(v) {} + TFontParam(const TFontParam &src) : TNotAnimatableParam(src) {} + TParam *clone() const override { return new TFontParam(*this); } + void loadData(TIStream &is) override; + void saveData(TOStream &os) override; +}; + +DEFINE_PARAM_SMARTPOINTER(TFontParam, std::wstring) + //----------------------------------------------------------------------------- // TNotAnimatableParamChangeUndo //----------------------------------------------------------------------------- diff --git a/toonz/sources/include/tools/tool.h b/toonz/sources/include/tools/tool.h index 7742ebf..91e4bdd 100644 --- a/toonz/sources/include/tools/tool.h +++ b/toonz/sources/include/tools/tool.h @@ -607,7 +607,8 @@ public: //! onionskins) //! (window coordinate, pixels, bottom-left origin) virtual int posToRow(const TPointD &p, double distance, - bool includeInvisible = true) const = 0; + bool includeInvisible = true, + bool currentColumnOnly = false) const = 0; //! return pos in pixel, bottom-left origin virtual TPointD worldToPos(const TPointD &worldPos) const = 0; diff --git a/toonz/sources/include/tools/toolhandle.h b/toonz/sources/include/tools/toolhandle.h index e11af61..e68dbb1 100644 --- a/toonz/sources/include/tools/toolhandle.h +++ b/toonz/sources/include/tools/toolhandle.h @@ -65,7 +65,13 @@ public: void notifyToolChanged() { emit toolChanged(); } void notifyToolCursorTypeChanged() { emit toolCursorTypeChanged(); } + + void notifyToolComboBoxListChanged(std::string id) { + emit toolComboBoxListChanged(id); + } + signals: + void toolComboBoxListChanged(std::string); void toolSwitched(); void toolChanged(); void toolEditingFinished(); diff --git a/toonz/sources/include/tools/tooloptions.h b/toonz/sources/include/tools/tooloptions.h index fe87b19..c5b503d 100644 --- a/toonz/sources/include/tools/tooloptions.h +++ b/toonz/sources/include/tools/tooloptions.h @@ -20,6 +20,7 @@ #include #include #include +#include // STD includes #include @@ -146,7 +147,7 @@ public: enum SingleValueWidgetType { SLIDER = 0, FIELD }; void setSingleValueWidgetType(int type) { m_singleValueWidgetType = type; } - enum EnumWidgetType { COMBOBOX = 0, POPUPBUTTON }; + enum EnumWidgetType { COMBOBOX = 0, POPUPBUTTON, FONTCOMBOBOX }; void setEnumWidgetType(int type) { m_enumWidgetType = type; } private: @@ -669,6 +670,36 @@ protected slots: void updateRealTimePickLabel(const int, const int, const int); }; +//============================================================================= +// +// ShiftTraceToolOptionBox +// shown only when "Edit Shift" mode is active +// +//============================================================================= + +class ShiftTraceToolOptionBox final : public ToolOptionsBox { + Q_OBJECT + QFrame *m_prevFrame, *m_afterFrame; + QRadioButton *m_prevRadioBtn, *m_afterRadioBtn; + QPushButton *m_resetPrevGhostBtn, *m_resetAfterGhostBtn; + TTool *m_tool; + void resetGhost(int index); + +protected: + void showEvent(QShowEvent *); + void hideEvent(QShowEvent *); + +public: + ShiftTraceToolOptionBox(QWidget *parent = 0, TTool *tool = 0); + void updateStatus() override; +protected slots: + void onResetPrevGhostBtnPressed(); + void onResetAfterGhostBtnPressed(); + void onPrevRadioBtnClicked(); + void onAfterRadioBtnClicked(); + void updateColors(); +}; + //----------------------------------------------------------------------------- class DVAPI ToolOptions final : public QFrame { diff --git a/toonz/sources/include/toonz/boardsettings.h b/toonz/sources/include/toonz/boardsettings.h new file mode 100644 index 0000000..98dacbb --- /dev/null +++ b/toonz/sources/include/toonz/boardsettings.h @@ -0,0 +1,141 @@ +#pragma once + +#ifndef BOARDSETTINGS_H +#define BOARDSETTINGS_H + +#include "traster.h" +#include "tfilepath.h" + +// TnzCore includes +#include "tstream.h" + +#include +#include +#include +#include + +#undef DVAPI +#undef DVVAR +#ifdef TOONZLIB_EXPORTS +#define DVAPI DV_EXPORT_API +#define DVVAR DV_EXPORT_VAR +#else +#define DVAPI DV_IMPORT_API +#define DVVAR DV_IMPORT_VAR +#endif + +class ToonzScene; + +class DVAPI BoardItem { +public: + enum Type { + FreeText = 0, + ProjectName, + SceneName, + Duration_Frame, + Duration_SecFrame, + Duration_HHMMSSFF, + CurrentDate, + CurrentDateTime, + UserName, + ScenePath_Aliased, + ScenePath_Full, + MoviePath_Aliased, + MoviePath_Full, + Image, + TypeCount + }; + +private: + QString m_name; + Type m_type; + + // item region, represented by ratio to the whole + QRectF m_rect; + + // Basically the font size will be automatically + // adjusted to fit the item region. + // The maximum font size can be used to make the font + // size smaller. + int m_maximumFontSize; + + // font color + QColor m_color; + + // font (familiy, bold, italic) + QFont m_font; + + QString m_text; + TFilePath m_imgPath; + Qt::AspectRatioMode m_imgARMode = Qt::KeepAspectRatio; + + QString getContentText(ToonzScene*); + +public: + BoardItem(); + + QRectF getRatioRect() { return m_rect; } + void setRatioRect(QRectF rect) { m_rect = rect; } + + // returns the item rect in pixels + QRectF getItemRect(QSize imgSize); + void drawItem(QPainter& p, QSize imgSize, int shrink, ToonzScene* scene); + + QString getName() { return m_name; } + void setName(QString name) { m_name = name; } + + Type getType() { return m_type; } + void setType(Type type) { m_type = type; } + + int getMaximumFontSize() { return m_maximumFontSize; } + void setMaximumFontSize(int size) { m_maximumFontSize = size; } + + QColor getColor() { return m_color; } + void setColor(QColor color) { m_color = color; } + + QFont& font() { return m_font; } + + QString getFreeText() { return m_text; } + void setFreeText(QString text) { m_text = text; } + + TFilePath getImgPath() { return m_imgPath; } + void setImgPath(TFilePath path) { m_imgPath = path; } + + Qt::AspectRatioMode getImgARMode() { return m_imgARMode; } + void setImgARMode(Qt::AspectRatioMode mode) { m_imgARMode = mode; } + + void saveData(TOStream& os); + void loadData(TIStream& is); +}; + +class DVAPI BoardSettings { + bool m_active = false; + int m_duration = 0; + QList m_items; + +public: + BoardSettings(); + + QImage getBoardImage(TDimension& dim, int shrink, ToonzScene* scene); + + TRaster32P getBoardRaster(TDimension& dim, int shrink, ToonzScene* scene); + + int getDuration() { return m_duration; } + + bool isActive() { return m_active; } + void setActive(bool on) { m_active = on; } + + int getItemCount() { return m_items.count(); } + BoardItem& getItem(int index) { return m_items[index]; } + + void setDuration(int f) { m_duration = f; } + + void addNewItem(int insertAt = 0); + void removeItem(int index); + void swapItems(int, int); + + void saveData(TOStream& os, bool forPreset = false); + void loadData(TIStream& is); +}; + +#endif \ No newline at end of file diff --git a/toonz/sources/include/toonz/mypaintbrushstyle.h b/toonz/sources/include/toonz/mypaintbrushstyle.h index d4895fb..05a3998 100644 --- a/toonz/sources/include/toonz/mypaintbrushstyle.h +++ b/toonz/sources/include/toonz/mypaintbrushstyle.h @@ -43,63 +43,59 @@ public: TMyPaintBrushStyle(const TMyPaintBrushStyle &other); ~TMyPaintBrushStyle(); - TColorStyle *clone() const override - { return new TMyPaintBrushStyle(*this); } + TColorStyle *clone() const override { return new TMyPaintBrushStyle(*this); } TColorStyle ©(const TColorStyle &other) override; static std::string getBrushType(); static TFilePathSet getBrushesDirs(); - const TFilePath& getPath() const - { return m_path; } - const mypaint::Brush& getBrush() const - { return m_brushModified; } - const TRasterP& getPreview() const - { return m_preview; } - - TStrokeProp* makeStrokeProp(const TStroke * /* stroke */) override - { return 0; } - TRegionProp* makeRegionProp(const TRegion * /* region */) override - { return 0; } - bool isRegionStyle() const override - { return false; } - bool isStrokeStyle() const override - { return false; } - - bool hasMainColor() const override - { return true; } - TPixel32 getMainColor() const override - { return m_color; } - void setMainColor(const TPixel32 &color) override - { m_color = color; } - - int getTagId() const override - { return 4001; } + const TFilePath &getPath() const { return m_path; } + const mypaint::Brush &getBrush() const { return m_brushModified; } + const TRasterP &getPreview() const { return m_preview; } + + TStrokeProp *makeStrokeProp(const TStroke * /* stroke */) override { + return 0; + } + TRegionProp *makeRegionProp(const TRegion * /* region */) override { + return 0; + } + bool isRegionStyle() const override { return false; } + bool isStrokeStyle() const override { return true; } + + bool hasMainColor() const override { return true; } + TPixel32 getMainColor() const override { return m_color; } + void setMainColor(const TPixel32 &color) override { m_color = color; } + + int getTagId() const override { return 4001; } QString getDescription() const override; void setBaseValue(MyPaintBrushSetting id, bool enable, float value); void resetBaseValues(); - void setBaseValue(MyPaintBrushSetting id, float value) - { setBaseValue(id, true, value); } + void setBaseValue(MyPaintBrushSetting id, float value) { + setBaseValue(id, true, value); + } - void setBaseValueEnabled(MyPaintBrushSetting id, bool enable) - { setBaseValue(id, enable, getBaseValue(id)); } + void setBaseValueEnabled(MyPaintBrushSetting id, bool enable) { + setBaseValue(id, enable, getBaseValue(id)); + } - const std::map getBaseValues() const - { return m_baseValues; } + const std::map getBaseValues() const { + return m_baseValues; + } float getBaseValue(MyPaintBrushSetting id) const { - std::map::const_iterator i = m_baseValues.find(id); - return i == m_baseValues.end() - ? m_brushOriginal.getBaseValue(id) - : i->second; + std::map::const_iterator i = + m_baseValues.find(id); + return i == m_baseValues.end() ? m_brushOriginal.getBaseValue(id) + : i->second; } bool getBaseValueEnabled(MyPaintBrushSetting id) const { - std::map::const_iterator i = m_baseValues.find(id); + std::map::const_iterator i = + m_baseValues.find(id); return i != m_baseValues.end(); } diff --git a/toonz/sources/include/toonz/onionskinmask.h b/toonz/sources/include/toonz/onionskinmask.h index f0b81b5..19cae20 100644 --- a/toonz/sources/include/toonz/onionskinmask.h +++ b/toonz/sources/include/toonz/onionskinmask.h @@ -7,6 +7,8 @@ #include "tcommon.h" #include "tgeometry.h" +#include + #undef DVAPI #undef DVVAR #ifdef TOONZLIB_EXPORTS @@ -114,6 +116,23 @@ since underlying onion-skinned drawings must be visible. } void setShiftTraceGhostCenter(int index, const TPointD ¢er); + const int getShiftTraceGhostFrameOffset(int index) { + return m_ghostFrame[index]; + } + void setShiftTraceGhostFrameOffset(int index, int offset) { + m_ghostFrame[index] = offset; + } + + const int getGhostFlipKey() { + return (m_ghostFlipKeys.isEmpty()) ? 0 : m_ghostFlipKeys.last(); + } + void appendGhostFlipKey(int key) { + m_ghostFlipKeys.removeAll(key); + m_ghostFlipKeys.append(key); + } + void removeGhostFlipKey(int key) { m_ghostFlipKeys.removeAll(key); } + void clearGhostFlipKey() { m_ghostFlipKeys.clear(); } + private: std::vector m_fos, m_mos; //!< Fixed and Mobile Onion Skin indices bool m_enabled; //!< Whether onion skin is enabled @@ -122,6 +141,9 @@ private: ShiftTraceStatus m_shiftTraceStatus; TAffine m_ghostAff[2]; TPointD m_ghostCenter[2]; + int m_ghostFrame[2]; // relative frame position of the ghosts + QList m_ghostFlipKeys; // If F1, F2 or F3 key is pressed, then only + // display the corresponding ghost }; //*************************************************************************** diff --git a/toonz/sources/include/toonz/preferences.h b/toonz/sources/include/toonz/preferences.h index 5d8aacc..2dc09f0 100644 --- a/toonz/sources/include/toonz/preferences.h +++ b/toonz/sources/include/toonz/preferences.h @@ -238,6 +238,8 @@ public: void setInterfaceFont(std::string font); QString getInterfaceFont() { return m_interfaceFont; } + void setInterfaceFontStyle(std::string style); + QString getInterfaceFontStyle() { return m_interfaceFontStyle; } void setInterfaceFontWeight(int weight); int getInterfaceFontWeight() { return m_interfaceFontWeight; } @@ -304,6 +306,11 @@ public: void setIgnoreImageDpi(bool on); bool isIgnoreImageDpiEnabled() const { return m_ignoreImageDpi; } + // Saving tab + + void setRasterBackgroundColor(const TPixel32 &color); + TPixel getRasterBackgroundColor() const { return m_rasterBackgroundColor; } + // Drawing tab void setScanLevelType(std::string s); @@ -505,6 +512,11 @@ public: } bool getOnionSkinDuringPlayback() { return m_onionSkinDuringPlayback; } void setOnionSkinDuringPlayback(bool on); + + void useOnionColorsForShiftAndTraceGhosts(bool on); + bool areOnionColorsUsedForShiftAndTraceGhosts() const { + return m_useOnionColorsForShiftAndTraceGhosts; + } // Transparency Check tab void setTranspCheckData(const TPixel &bg, const TPixel &ink, @@ -573,6 +585,11 @@ public: } //! \sa The \p sysctl unix command. std::string getLayerNameEncoding() const { return m_layerNameEncoding; }; + // Tablet tab + + void enableWinInk(bool on); + bool isWinInkEnabled() const { return m_enableWinInk; } + Q_SIGNALS: void stopAutoSave(); @@ -589,7 +606,7 @@ private: QString m_units, m_cameraUnits, m_scanLevelType, m_currentRoomChoice, m_oldUnits, m_oldCameraUnits, m_ffmpegPath, m_shortcutPreset, - m_customProjectRoot, m_interfaceFont; + m_customProjectRoot, m_interfaceFont, m_interfaceFontStyle; QString m_fastRenderPath; double m_defLevelWidth, m_defLevelHeight, m_defLevelDpi; @@ -702,7 +719,10 @@ private: QString m_cursorBrushStyle; bool m_cursorOutlineEnabled = false; - TPixel32 m_currentColumnColor; + TPixel32 m_currentColumnColor, m_rasterBackgroundColor; + + bool m_enableWinInk = false; + bool m_useOnionColorsForShiftAndTraceGhosts = false; private: Preferences(); diff --git a/toonz/sources/include/toonz/stageplayer.h b/toonz/sources/include/toonz/stageplayer.h index cdb6a8b..d1aa926 100644 --- a/toonz/sources/include/toonz/stageplayer.h +++ b/toonz/sources/include/toonz/stageplayer.h @@ -107,6 +107,8 @@ public: static double m_firstBackOnionSkin; static double m_lastBackVisibleSkin; + static bool m_isShiftAndTraceEnabled; + TPixel32 m_filterColor; public: diff --git a/toonz/sources/include/toonz/stagevisitor.h b/toonz/sources/include/toonz/stagevisitor.h index 4461362..6d134e5 100644 --- a/toonz/sources/include/toonz/stagevisitor.h +++ b/toonz/sources/include/toonz/stagevisitor.h @@ -252,6 +252,8 @@ private: // darken blended view mode for viewing the non-cleanuped and stacked drawings bool m_doRasterDarkenBlendedView; + std::vector m_guidedStrokes; + public: RasterPainter(const TDimension &dim, const TAffine &viewAff, const TRect &rect, const ImagePainter::VisualSettings &vs, @@ -279,6 +281,8 @@ public: bool isSingleColumnEnabled() const { return m_singleColumnEnabled; } void setRasterDarkenBlendedView(bool on) { m_doRasterDarkenBlendedView = on; } + + std::vector &getGuidedStrokes() { return m_guidedStrokes; } }; //============================================================================= @@ -289,6 +293,8 @@ class DVAPI Picker final : public Visitor { TAffine m_viewAff; double m_minDist2; + int m_currentColumnIndex = -1; + public: Picker(const TAffine &viewAff, const TPointD &p, const ImagePainter::VisualSettings &vs); @@ -304,6 +310,8 @@ public: int getColumnIndex() const; void getColumnIndexes(std::vector &indexes) const; int getRow() const; + + void setCurrentColumnIndex(int index) { m_currentColumnIndex = index; } }; //============================================================================= diff --git a/toonz/sources/include/toonz/txshcolumn.h b/toonz/sources/include/toonz/txshcolumn.h index 80e5aaf..fe3fb0f 100644 --- a/toonz/sources/include/toonz/txshcolumn.h +++ b/toonz/sources/include/toonz/txshcolumn.h @@ -265,6 +265,8 @@ Set column color tag to \b colorTag. TPixel32 getFilterColor(); static QPair getFilterInfo(FilterColor key); static void initColorFilters(); + + void resetColumnProperties(); }; #ifdef _WIN32 diff --git a/toonz/sources/include/toonzqt/colorfield.h b/toonz/sources/include/toonzqt/colorfield.h index 19b9c02..9aa5683 100644 --- a/toonz/sources/include/toonzqt/colorfield.h +++ b/toonz/sources/include/toonzqt/colorfield.h @@ -96,7 +96,7 @@ class DVAPI ChannelField final : public QWidget { public: ChannelField(QWidget *parent = 0, const QString &string = "", int value = 0, int maxValue = 255, bool horizontal = false, int labelWidth = 13, - int sliderWidth = 40); + int sliderWidth = -1); ~ChannelField() {} @@ -145,7 +145,7 @@ public: ColorField(QWidget *parent = 0, bool isAlphaActive = true, TPixel32 color = TPixel32(0, 0, 0, 255), int squareSize = 40, - bool useStyleEditor = true); + bool useStyleEditor = true, int sliderWidth = -1); ~ColorField() {} diff --git a/toonz/sources/include/toonzqt/fxschematicnode.h b/toonz/sources/include/toonzqt/fxschematicnode.h index 0c5a299..f0d7a7a 100644 --- a/toonz/sources/include/toonzqt/fxschematicnode.h +++ b/toonz/sources/include/toonzqt/fxschematicnode.h @@ -45,6 +45,7 @@ class FxColumnPainter final : public QObject, public QGraphicsItem { double m_width, m_height; QString m_name; int m_type; + bool m_isReference = false; public: FxColumnPainter(FxSchematicColumnNode *parent, double width, double height, @@ -55,6 +56,7 @@ public: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override; void setName(const QString &name) { m_name = name; } + void setIsReference(bool ref = true) { m_isReference = ref; } public slots: @@ -224,8 +226,8 @@ private: void resetSnappedLinksOnDynamicPortFx(); - void hideSnappedLinks() override; - void showSnappedLinks() override; + void hideSnappedLinks(SchematicPort *) override; + void showSnappedLinks(SchematicPort *) override; }; //***************************************************** diff --git a/toonz/sources/include/toonzqt/fxschematicscene.h b/toonz/sources/include/toonzqt/fxschematicscene.h index 87c071a..1907db2 100644 --- a/toonz/sources/include/toonzqt/fxschematicscene.h +++ b/toonz/sources/include/toonzqt/fxschematicscene.h @@ -228,6 +228,8 @@ protected slots: void onIconifyNodesToggled(bool iconified); + void onNodeChangedSize(); + private: void setEnableCache(bool toggle); diff --git a/toonz/sources/include/toonzqt/glwidget_for_highdpi.h b/toonz/sources/include/toonzqt/glwidget_for_highdpi.h index 2bee6b4..258e17c 100644 --- a/toonz/sources/include/toonzqt/glwidget_for_highdpi.h +++ b/toonz/sources/include/toonzqt/glwidget_for_highdpi.h @@ -11,7 +11,7 @@ class GLWidgetForHighDpi : public QOpenGLWidget, protected QOpenGLFunctions { public: - GLWidgetForHighDpi(QWidget *parent = Q_NULLPTR, + GLWidgetForHighDpi(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()) : QOpenGLWidget(parent, f) {} diff --git a/toonz/sources/include/toonzqt/paletteviewergui.h b/toonz/sources/include/toonzqt/paletteviewergui.h index e853458..5e03c6d 100644 --- a/toonz/sources/include/toonzqt/paletteviewergui.h +++ b/toonz/sources/include/toonzqt/paletteviewergui.h @@ -50,22 +50,6 @@ class StyleNameEditor; namespace PaletteViewerGUI { -// class for managing the palette's default style chip size -class DVAPI ChipSizeManager { -public: - int chipSize_Palette; - int chipSize_Cleanup; - int chipSize_Studio; - static ChipSizeManager *instance() { - static ChipSizeManager _instance; - return &_instance; - } - -private: - ChipSizeManager() - : chipSize_Palette(2), chipSize_Cleanup(2), chipSize_Studio(2) {} -}; - enum PaletteViewType //! Possible palette contents of a Palette Viewer. { LEVEL_PALETTE, //!< Content palette is from a level. CLEANUP_PALETTE, //!< Content palette is from cleanup settings. diff --git a/toonz/sources/include/toonzqt/paramfield.h b/toonz/sources/include/toonzqt/paramfield.h index 858f823..dbf3880 100644 --- a/toonz/sources/include/toonzqt/paramfield.h +++ b/toonz/sources/include/toonzqt/paramfield.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "tgeometry.h" #include "tparam.h" @@ -40,6 +41,7 @@ class QString; class QComboBox; class QHBoxLayout; class TFxHandle; +class QFontComboBox; namespace DVGui { class LineEdit; @@ -501,11 +503,28 @@ protected slots: // StringParamField //----------------------------------------------------------------------------- +namespace component { +class MyTextEdit : public QTextEdit { + Q_OBJECT +public: + MyTextEdit(const QString &text, QWidget *parent = Q_NULLPTR) + : QTextEdit(text, parent) {} + +protected: + void keyPressEvent(QKeyEvent *event) override; + void focusOutEvent(QFocusEvent *e) override; + +signals: + void edited(); +}; +}; + class DVAPI StringParamField final : public ParamField { Q_OBJECT TStringParamP m_currentParam, m_actualParam; - DVGui::LineEdit *m_textFld; + DVGui::LineEdit *m_textFld = nullptr; + component::MyTextEdit *m_multiTextFld = nullptr; public: StringParamField(QWidget *parent, QString name, const TStringParamP ¶m); @@ -514,8 +533,41 @@ public: int frame) override; void update(int frame) override; - QSize getPreferedSize() override { return QSize(100, 20); } + QSize getPreferedSize() override { + if (m_textFld) + return QSize(100, 20); + else + return QSize(100, 80); + } +protected slots: + void onChange(); +}; + +//============================================================================= +// FontParamField +//----------------------------------------------------------------------------- + +class FontParamField final : public ParamField { + Q_OBJECT + + TFontParamP m_currentParam, m_actualParam; + + QFontComboBox *m_fontCombo; + QComboBox *m_styleCombo; + DVGui::IntField *m_sizeField; + +public: + FontParamField(QWidget *parent, QString name, const TFontParamP ¶m); + + void setParam(const TParamP ¤t, const TParamP &actual, + int frame) override; + void update(int frame) override; + + QSize getPreferedSize() override { return QSize(150, 20); } + protected slots: + void findStyles(const QFont &font); + void onSizeChange(bool); void onChange(); }; diff --git a/toonz/sources/include/toonzqt/popupbutton.h b/toonz/sources/include/toonzqt/popupbutton.h index 0ee8081..ecaaca2 100644 --- a/toonz/sources/include/toonzqt/popupbutton.h +++ b/toonz/sources/include/toonzqt/popupbutton.h @@ -20,7 +20,6 @@ #include #include #include -#include #include // Forward declarations diff --git a/toonz/sources/include/toonzqt/schematicnode.h b/toonz/sources/include/toonzqt/schematicnode.h index d50a859..67a4c77 100644 --- a/toonz/sources/include/toonzqt/schematicnode.h +++ b/toonz/sources/include/toonzqt/schematicnode.h @@ -245,6 +245,8 @@ public: void updatePath(SchematicPort *startPort, SchematicPort *endPort); void updatePath() { updatePath(m_startPort, m_endPort); } + void updateEndPos(const QPointF &endPos); + //! Sets the start SchematicPort of the link to \b startPort. void setStartPort(SchematicPort *startPort) { m_startPort = startPort; } //! Sets the start SchematicPort of the link to \b startPort. @@ -309,7 +311,7 @@ protected: SchematicNode *m_node; QPointF m_hook; bool m_highlighted; - SchematicLink *m_ghostLink; + QList m_ghostLinks; SchematicPort *m_linkingTo; QList m_links; int m_type; @@ -390,8 +392,11 @@ protected: private: virtual SchematicPort *searchPort(const QPointF &scenePos) = 0; - virtual void hideSnappedLinks() = 0; - virtual void showSnappedLinks() = 0; + + // linkingPort is used only for stage schematic port - + // in order to enable to connect from multiple node at the same time. + virtual void hideSnappedLinks(SchematicPort *linkingPort) = 0; + virtual void showSnappedLinks(SchematicPort *linkingPort) = 0; signals: void isClicked(); @@ -446,6 +451,7 @@ protected: signals: void sceneChanged(); void xsheetChanged(); + void nodeChangedSize(); }; #endif // SCHEMATICNODE_H diff --git a/toonz/sources/include/toonzqt/schematicviewer.h b/toonz/sources/include/toonzqt/schematicviewer.h index 5e7ec60..abc4bb8 100644 --- a/toonz/sources/include/toonzqt/schematicviewer.h +++ b/toonz/sources/include/toonzqt/schematicviewer.h @@ -227,6 +227,10 @@ class DVAPI SchematicViewer final : public QWidget { Q_PROPERTY( QColor MeshColumnColor READ getMeshColumnColor WRITE setMeshColumnColor) + // Reference column + QColor m_referenceColumnColor; + Q_PROPERTY(QColor ReferenceColumnColor MEMBER m_referenceColumnColor) + // Table node QColor m_tableColor; Q_PROPERTY(QColor TableColor READ getTableColor WRITE setTableColor) @@ -370,6 +374,9 @@ public: void setMeshColumnColor(const QColor &color) { m_meshColumnColor = color; } QColor getMeshColumnColor() const { return m_meshColumnColor; } + // Reference column + QColor getReferenceColumnColor() const { return m_referenceColumnColor; } + // Table node void setTableColor(const QColor &color) { m_tableColor = color; } QColor getTableColor() const { return m_tableColor; } diff --git a/toonz/sources/include/toonzqt/stageschematicnode.h b/toonz/sources/include/toonzqt/stageschematicnode.h index c70a8c2..eca404c 100644 --- a/toonz/sources/include/toonzqt/stageschematicnode.h +++ b/toonz/sources/include/toonzqt/stageschematicnode.h @@ -47,6 +47,7 @@ class ColumnPainter final : public QObject, public QGraphicsItem { double m_width, m_height; QString m_name; int m_type; + bool m_isReference = false; public: ColumnPainter(StageSchematicColumnNode *parent, double width, double height, @@ -56,6 +57,7 @@ public: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override; void setName(const QString &name) { m_name = name; } + void setIsReference(bool ref = true) { m_isReference = ref; } QLinearGradient getGradientByLevelType(int type); @@ -222,8 +224,8 @@ public: private: SchematicPort *searchPort(const QPointF &scenePos) override; - void hideSnappedLinks() override; - void showSnappedLinks() override; + void hideSnappedLinks(SchematicPort *linkingPort) override; + void showSnappedLinks(SchematicPort *linkingPort) override; }; //======================================================== @@ -247,8 +249,8 @@ public: private: SchematicPort *searchPort(const QPointF &scenePos) override; - void hideSnappedLinks() override; - void showSnappedLinks() override; + void hideSnappedLinks(SchematicPort *) override; + void showSnappedLinks(SchematicPort *) override; }; //======================================================== diff --git a/toonz/sources/include/toonzqt/stageschematicscene.h b/toonz/sources/include/toonzqt/stageschematicscene.h index b39aa9f..bf155c8 100644 --- a/toonz/sources/include/toonzqt/stageschematicscene.h +++ b/toonz/sources/include/toonzqt/stageschematicscene.h @@ -215,6 +215,7 @@ protected slots: void onSelectionChanged(); void onCollapse(QList); void onEditGroup(); + void onNodeChangedSize(); void onSwitchPortModeToggled(bool withLetter); }; diff --git a/toonz/sources/include/toonzqt/studiopaletteviewer.h b/toonz/sources/include/toonzqt/studiopaletteviewer.h index 14460d5..c8fdf64 100644 --- a/toonz/sources/include/toonzqt/studiopaletteviewer.h +++ b/toonz/sources/include/toonzqt/studiopaletteviewer.h @@ -26,7 +26,7 @@ class TFrameHandle; class PalettesScanPopup; class TXsheetHandle; class TXshLevelHandle; - +class PaletteViewer; //============================================================================= //! The StudioPaletteTreeViewer class provides an object to view and manage //! palettes files. @@ -207,6 +207,7 @@ class DVAPI StudioPaletteViewer final : public QSplitter { Q_OBJECT StudioPaletteTreeViewer *m_studioPaletteTreeViewer; + PaletteViewer *m_studioPaletteViewer; public: StudioPaletteViewer(QWidget *parent, TPaletteHandle *studioPaletteHandle, @@ -217,6 +218,9 @@ public: /*! In order to save current palette from the tool button in the PageViewer.*/ TFilePath getCurrentItemPath(); + + int getViewMode() const; + void setViewMode(int mode); }; #endif // STUDIOPALETTEVIEWER_H diff --git a/toonz/sources/include/toonzqt/styleindexlineedit.h b/toonz/sources/include/toonzqt/styleindexlineedit.h index 7dd8438..f746286 100644 --- a/toonz/sources/include/toonzqt/styleindexlineedit.h +++ b/toonz/sources/include/toonzqt/styleindexlineedit.h @@ -25,6 +25,8 @@ class TPaletteHandle; namespace DVGui { class DVAPI StyleIndexLineEdit : public LineEdit { + Q_OBJECT + TPaletteHandle *m_pltHandle; public: diff --git a/toonz/sources/include/toonzqt/stylenameeditor.h b/toonz/sources/include/toonzqt/stylenameeditor.h index 2852bf8..1865e5c 100644 --- a/toonz/sources/include/toonzqt/stylenameeditor.h +++ b/toonz/sources/include/toonzqt/stylenameeditor.h @@ -24,7 +24,7 @@ class NewWordDialog : public QDialog { QLineEdit *m_lineEdit; public: - NewWordDialog(QWidget *parent = Q_NULLPTR); + NewWordDialog(QWidget *parent = nullptr); QString getName(); }; @@ -33,7 +33,7 @@ public: class WordButton : public QPushButton { Q_OBJECT public: - WordButton(const QString &text, QWidget *parent = Q_NULLPTR); + WordButton(const QString &text, QWidget *parent = nullptr); protected: void contextMenuEvent(QContextMenuEvent *) override; @@ -54,7 +54,7 @@ class AddWordButton final : public WordButton { int m_column; public: - AddWordButton(const int col, QWidget *parent = Q_NULLPTR); + AddWordButton(const int col, QWidget *parent = nullptr); protected slots: void onClicked() override; diff --git a/toonz/sources/include/toutputproperties.h b/toonz/sources/include/toutputproperties.h index 8c48652..ded931c 100644 --- a/toonz/sources/include/toutputproperties.h +++ b/toonz/sources/include/toutputproperties.h @@ -20,6 +20,7 @@ class TPropertyGroup; class TWidget; class TRenderSettings; +class BoardSettings; //============================================================================= //! The TOutputProperties class provides a container for output properties and @@ -91,6 +92,8 @@ private: bool m_subcameraPreview; + BoardSettings *m_boardSettings; + public: /*! Constructs TOutputProperties with default value. @@ -216,6 +219,8 @@ machine's CPU). bool isSubcameraPreview() const { return m_subcameraPreview; } void setSubcameraPreview(bool enabled) { m_subcameraPreview = enabled; } + + BoardSettings *getBoardSettings() const { return m_boardSettings; } }; //-------------------------------------------- diff --git a/toonz/sources/include/tvectorgl.h b/toonz/sources/include/tvectorgl.h index 2909c98..0e8a196 100644 --- a/toonz/sources/include/tvectorgl.h +++ b/toonz/sources/include/tvectorgl.h @@ -49,7 +49,8 @@ class TVectorRenderData; \par stroke is element to draw \par rd: \sa TVectorRenderData */ -void DVAPI tglDraw(const TVectorRenderData &rd, const TVectorImage *vim); +void DVAPI tglDraw(const TVectorRenderData &rd, const TVectorImage *vim, + TStroke **guidedStroke = (TStroke **)nullptr); void DVAPI tglDrawMask(const TVectorRenderData &rd, const TVectorImage *vim); void DVAPI tglDraw(const TVectorRenderData &rd, const TStroke *stroke, bool pushAttribs = true); diff --git a/toonz/sources/stdfx/CMakeLists.txt b/toonz/sources/stdfx/CMakeLists.txt index b691a4e..f0a0017 100644 --- a/toonz/sources/stdfx/CMakeLists.txt +++ b/toonz/sources/stdfx/CMakeLists.txt @@ -72,9 +72,10 @@ set(HEADERS iwa_fresnel.h iwa_pnperspectivefx.h iwa_soapbubblefx.h - iwa_bokehfx.h - iwa_timecodefx.h - iwa_bokehreffx.h + iwa_bokehfx.h + iwa_timecodefx.h + iwa_bokehreffx.h + iwa_textfx.h ) set(SOURCES @@ -250,12 +251,13 @@ set(SOURCES iwa_noise1234.cpp iwa_pnperspectivefx.cpp iwa_soapbubblefx.cpp - ${SDKROOT}/kiss_fft130/kiss_fft.c - ${SDKROOT}/kiss_fft130/tools/kiss_fftnd.c - iwa_bokehfx.cpp - iwa_timecodefx.cpp - iwa_bokehreffx.cpp - iwa_barreldistortfx.cpp + ${SDKROOT}/kiss_fft130/kiss_fft.c + ${SDKROOT}/kiss_fft130/tools/kiss_fftnd.c + iwa_bokehfx.cpp + iwa_timecodefx.cpp + iwa_bokehreffx.cpp + iwa_barreldistortfx.cpp + iwa_textfx.cpp ) set(OBJCSOURCES diff --git a/toonz/sources/stdfx/changecolorfx.cpp b/toonz/sources/stdfx/changecolorfx.cpp index 2f776b6..c23048a 100644 --- a/toonz/sources/stdfx/changecolorfx.cpp +++ b/toonz/sources/stdfx/changecolorfx.cpp @@ -182,7 +182,7 @@ to_v =to_hsv[2]/255.; double hmax = from_h + range * 180; hmax = normalize_h(hmax); if (hmax <= hmin) { - tswap(hmin, hmax); + std::swap(hmin, hmax); swaprange = true; } double smin = from_s - range; diff --git a/toonz/sources/stdfx/freedistortfx.cpp b/toonz/sources/stdfx/freedistortfx.cpp index 6f17afa..8e3dfab 100644 --- a/toonz/sources/stdfx/freedistortfx.cpp +++ b/toonz/sources/stdfx/freedistortfx.cpp @@ -232,8 +232,8 @@ TPointD p11_b = m_p11_b->getValue(frame); if (m_isCastShadow) { - tswap(p00_a, p01_a); -tswap(p10_a, p11_a); + std::swap(p00_a, p01_a); +std::swap(p10_a, p11_a); }*/ /*TRectD source; @@ -306,8 +306,8 @@ void FreeDistortBaseFx::transform(double frame, int port, if (m_isCastShadow) { // Shadows are mirrored - tswap(p00_a, p01_a); - tswap(p10_a, p11_a); + std::swap(p00_a, p01_a); + std::swap(p10_a, p11_a); } // Build the input affine @@ -723,8 +723,8 @@ void FreeDistortBaseFx::doCompute(TTile &tile, double frame, if (m_isCastShadow) { // Shadows are mirrored - tswap(p00_a, p01_a); - tswap(p10_a, p11_a); + std::swap(p00_a, p01_a); + std::swap(p10_a, p11_a); } // Get requested tile's geometry diff --git a/toonz/sources/stdfx/igs_line_blur.cpp b/toonz/sources/stdfx/igs_line_blur.cpp index 0a9fac8..ac9fc9d 100644 --- a/toonz/sources/stdfx/igs_line_blur.cpp +++ b/toonz/sources/stdfx/igs_line_blur.cpp @@ -322,13 +322,6 @@ typedef int int32_t; #include /* for int32_t */ #endif -#ifndef ON -#define ON (1) -#endif -#ifndef OFF -#define OFF (0) -#endif - #ifndef OK #define OK (0) #endif @@ -346,9 +339,9 @@ public: brush_curve_blur(void) { int32_t ii; - this->_i_mv_sw = OFF; - this->_i_pv_sw = OFF; - this->_i_cv_sw = OFF; + this->_i_mv_sw = false; + this->_i_pv_sw = false; + this->_i_cv_sw = false; this->_i32_count = 51; this->_i32_subpixel_divide = 2; @@ -368,9 +361,9 @@ public: ~brush_curve_blur(void) { this->mem_free(); } /* パラメータ設定 */ - void set_i_mv_sw(int ii) { this->_i_mv_sw = ii; } - void set_i_pv_sw(int ii) { this->_i_pv_sw = ii; } - void set_i_cv_sw(int ii) { this->_i_cv_sw = ii; } + void set_i_mv_sw(bool ii) { this->_i_mv_sw = ii; } + void set_i_pv_sw(bool ii) { this->_i_pv_sw = ii; } + void set_i_cv_sw(bool ii) { this->_i_cv_sw = ii; } /* ぼかし線のポイント数 */ void set_i32_count(int32_t ii) { this->_i32_count = ii; } @@ -401,9 +394,9 @@ public: void debug_print(void); private: - int _i_mv_sw, /* Method Verbose */ - _i_pv_sw, /* Parameter Verbose */ - _i_cv_sw; /* Counter Verbose */ + bool _i_mv_sw; /* Method Verbose */ + bool _i_pv_sw; /* Parameter Verbose */ + bool _i_cv_sw; /* Counter Verbose */ int32_t _i32_count; int32_t _i32_subpixel_divide; @@ -423,7 +416,7 @@ private: /* メモリ開放 */ void brush_curve_blur::mem_free(void) { if (NULL != this->_dp_ratio) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("brush_curve_blur::mem_free()"); } free(this->_dp_ratio); @@ -446,10 +439,10 @@ int brush_curve_blur::mem_alloc(void) { } /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("brush_curve_blur::mem_alloc()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr( "alloc brush_curve_blur memory ((%d * %d) + %d) x %d bytes", this->_i32_count, (1 + CHANNEL_COUNT + 2), /* ratio,accum,xp,yp */ @@ -638,13 +631,6 @@ typedef unsigned short uint16_t; #include /* for int32_t, uint16_t */ #endif -#ifndef ON -#define ON (1) -#endif -#ifndef OFF -#define OFF (0) -#endif - #ifndef OK #define OK (0) #endif @@ -655,9 +641,9 @@ typedef unsigned short uint16_t; class brush_smudge_circle { public: brush_smudge_circle() { - this->_i_mv_sw = OFF; - this->_i_pv_sw = OFF; - this->_i_cv_sw = OFF; + this->_i_mv_sw = false; + this->_i_pv_sw = false; + this->_i_cv_sw = false; this->_i32_size_by_pixel = 7; /* 画像上の線の最大幅 */ this->_i32_subpixel_divide = 4; @@ -670,9 +656,9 @@ public: ~brush_smudge_circle() { this->mem_free(); } /* パラメータ設定 */ - void set_i_mv_sw(int ii) { this->_i_mv_sw = ii; } - void set_i_pv_sw(int ii) { this->_i_pv_sw = ii; } - void set_i_cv_sw(int ii) { this->_i_cv_sw = ii; } + void set_i_mv_sw(bool ii) { this->_i_mv_sw = ii; } + void set_i_pv_sw(bool ii) { this->_i_pv_sw = ii; } + void set_i_cv_sw(bool ii) { this->_i_cv_sw = ii; } void set_i32_size_by_pixel(int32_t ii) { this->_i32_size_by_pixel = ii; } void set_i32_subpixel_divide(int32_t ii) { this->_i32_subpixel_divide = ii; } @@ -707,9 +693,9 @@ public: void mem_free(void); private: - int _i_mv_sw, /* Method Verbose */ - _i_pv_sw, /* Parameter Verbose */ - _i_cv_sw; /* Counter Verbose */ + bool _i_mv_sw; /* Method Verbose */ + bool _i_pv_sw; /* Parameter Verbose */ + bool _i_cv_sw; /* Counter Verbose */ int32_t _i32_size_by_pixel, _i32_subpixel_divide; double _d_ratio; @@ -728,7 +714,7 @@ private: /* メモリ開放 */ void brush_smudge_circle::mem_free(void) { if (NULL != this->_dp_brush) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("brush_smudge_circle::mem_free()"); } free(this->_dp_brush); @@ -749,11 +735,11 @@ int brush_smudge_circle::mem_alloc(void) { i32_sz = this->_i32_size_by_pixel * this->_i32_subpixel_divide; /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("brush_smudge_circle::mem_alloc()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("calloc((%d x %d + %d x %d + %d x %d) x (%d x %d))", i32_sz, i32_sz, i32_sz, i32_sz, (this->_i32_size_by_pixel + 1), @@ -1278,25 +1264,18 @@ void pixel_point_node::print_xy_around(void) { #include "igs_line_blur.h" // "list_root.h" "pixel_point_node.h" -#ifndef ON -#define ON (1) -#endif -#ifndef OFF -#define OFF (0) -#endif - class pixel_point_root final : public list_root { public: pixel_point_root(void) { - this->_i_mv_sw = OFF; - this->_i_cv_sw = OFF; - this->_i_pv_sw = OFF; + this->_i_mv_sw = false; + this->_i_cv_sw = false; + this->_i_pv_sw = false; } ~pixel_point_root(void) { this->mem_free(); } - void set_i_mv_sw(int sw) { this->_i_mv_sw = sw; } - void set_i_cv_sw(int sw) { this->_i_cv_sw = sw; } - void set_i_pv_sw(int sw) { this->_i_pv_sw = sw; } + void set_i_mv_sw(bool sw) { this->_i_mv_sw = sw; } + void set_i_cv_sw(bool sw) { this->_i_cv_sw = sw; } + void set_i_pv_sw(bool sw) { this->_i_pv_sw = sw; } /* 16Bits 1channel画像からゼロ以上のピクセルをプロットする */ int alloc_mem_and_list_node(int32_t i32_xs, int32_t i32_ys, @@ -1311,7 +1290,7 @@ public: void mem_free(void); private: - int _i_mv_sw, _i_cv_sw, _i_pv_sw; + bool _i_mv_sw, _i_cv_sw, _i_pv_sw; /* リストの削除 */ void _remove(pixel_point_node *clp_target); @@ -1346,7 +1325,7 @@ void pixel_point_root::mem_free(void) { int32_t ii; if (NULL != this->get_clp_last()) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_point_root::mem_free()"); } ii = 0; @@ -1354,7 +1333,7 @@ void pixel_point_root::mem_free(void) { this->_remove(clp_); ++ii; } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("free point node %d", ii); } } @@ -1366,19 +1345,19 @@ int pixel_point_root::alloc_mem_and_list_node(int32_t i32_xs, int32_t i32_ys, pixel_point_node *clp_pp; /* 処理実行表示 */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_point_root::alloc_mem_and_list_node()"); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(i32_ys); } clp_pp = NULL; for (yy = 0; yy < i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(yy); } @@ -1395,12 +1374,12 @@ int pixel_point_root::alloc_mem_and_list_node(int32_t i32_xs, int32_t i32_ys, } } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } /* 処理結果表示 */ - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("alloc and list %d points", this->get_i32_count()); } @@ -2422,17 +2401,17 @@ private: class pixel_select_same_way_root final : public list_root { public: pixel_select_same_way_root(void) { - this->_i_mv_sw = OFF; - this->_i_cv_sw = OFF; - this->_i_pv_sw = OFF; + this->_i_mv_sw = false; + this->_i_cv_sw = false; + this->_i_pv_sw = false; this->_i32_count_max = 4; this->_d_length_max = 160; } ~pixel_select_same_way_root(void) { this->mem_free(); } - void set_i_mv_sw(int sw) { this->_i_mv_sw = sw; } - void set_i_cv_sw(int sw) { this->_i_cv_sw = sw; } - void set_i_pv_sw(int sw) { this->_i_pv_sw = sw; } + void set_i_mv_sw(bool sw) { this->_i_mv_sw = sw; } + void set_i_cv_sw(bool sw) { this->_i_cv_sw = sw; } + void set_i_pv_sw(bool sw) { this->_i_pv_sw = sw; } int32_t get_i32_count_max(void) { return this->_i32_count_max; } void set_i32_count_max(int32_t ii) { this->_i32_count_max = ii; } @@ -2448,7 +2427,7 @@ public: void mem_free(void); private: - int _i_mv_sw, _i_cv_sw, _i_pv_sw; + bool _i_mv_sw, _i_cv_sw, _i_pv_sw; int32_t _i32_count_max; double _d_length_max; @@ -2503,7 +2482,7 @@ void pixel_select_same_way_root::mem_free(void) { int32_t ii; if (NULL != this->get_clp_last()) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_select_same_way_root::mem_free()"); } @@ -2513,7 +2492,7 @@ void pixel_select_same_way_root::mem_free(void) { this->_remove(clp_); ++ii; } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("free select same way node %d", ii); } } @@ -2718,9 +2697,9 @@ void pixel_select_same_way_root::get_vector(double *dp_xv, double *dp_yv) { class pixel_line_root final : public list_root { public: pixel_line_root(void) { - this->_i_mv_sw = OFF; - this->_i_cv_sw = OFF; - this->_i_pv_sw = OFF; + this->_i_mv_sw = false; + this->_i_cv_sw = false; + this->_i_pv_sw = false; this->_d_bbox_x_min = 0.0; this->_d_bbox_x_max = 0.0; @@ -2728,12 +2707,12 @@ public: this->_d_bbox_y_max = 0.0; this->_i32_smooth_retry = 100; - this->_i_same_way_exec_sw = ON; + this->_i_same_way_exec_sw = true; } ~pixel_line_root(void) { this->mem_free(); } - void set_i_mv_sw(int sw) { this->_i_mv_sw = sw; } - void set_i_cv_sw(int sw) { this->_i_cv_sw = sw; } - void set_i_pv_sw(int sw) { this->_i_pv_sw = sw; } + void set_i_mv_sw(bool sw) { this->_i_mv_sw = sw; } + void set_i_cv_sw(bool sw) { this->_i_cv_sw = sw; } + void set_i_pv_sw(bool sw) { this->_i_pv_sw = sw; } double get_d_bbox_x_min(void) { return this->_d_bbox_x_min; } double get_d_bbox_x_max(void) { return this->_d_bbox_x_max; } @@ -2742,7 +2721,7 @@ public: void set_i32_smooth_retry(int32_t i32) { this->_i32_smooth_retry = i32; } int32_t get_i32_smooth_retry(void) { return this->_i32_smooth_retry; } - void set_i_same_way_exec_sw(int sw) { this->_i_same_way_exec_sw = sw; } + void set_i_same_way_exec_sw(bool sw) { this->_i_same_way_exec_sw = sw; } int exec01020304(pixel_point_root *clp_pixel_point_root); void exec05_set_middle(void); @@ -2768,12 +2747,12 @@ public: void mem_free(void); private: - int _i_mv_sw, _i_cv_sw, _i_pv_sw; + bool _i_mv_sw, _i_cv_sw, _i_pv_sw; double _d_bbox_x_min, _d_bbox_x_max, _d_bbox_y_min, _d_bbox_y_max; int32_t _i32_smooth_retry; - int _i_same_way_exec_sw; + bool _i_same_way_exec_sw; calculator_geometry _cl_cal_geom; @@ -2827,7 +2806,7 @@ int pixel_line_root::_exec01_link_left_right( pixel_point_node *clp_point, *clp_point2; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::_exec01_link_left_right()"); } @@ -2858,7 +2837,7 @@ int pixel_line_root::_exec01_link_left_right( clp_point2 = clp_point; } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" link left right %d", ii); } @@ -2869,7 +2848,7 @@ int pixel_line_root::_exec02_link_up_down( pixel_point_node *clp_point, *clp_point2; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::_exec02_link_up_down()"); } @@ -2907,7 +2886,7 @@ int pixel_line_root::_exec02_link_up_down( } } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" link up down %d", ii); } @@ -2919,9 +2898,9 @@ int pixel_line_root::_exec03_link_slant( pixel_point_node *clp_point, *clp_point2, *clp_point_link; int32_t ii, jj; - int i_left_link_sw, i_right_link_sw, i_up_link_sw; + bool i_left_link_sw, i_right_link_sw, i_up_link_sw; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::_exec03_link_slant()"); } @@ -2936,9 +2915,9 @@ int pixel_line_root::_exec03_link_slant( continue; } - i_left_link_sw = OFF; - i_right_link_sw = OFF; - i_up_link_sw = OFF; + i_left_link_sw = false; + i_right_link_sw = false; + i_up_link_sw = false; /* 全リンクの調査 */ for (jj = 0; jj < LINK_NEAR_COUNT; ++jj) { @@ -2948,24 +2927,24 @@ int pixel_line_root::_exec03_link_slant( /* 上につながっている */ if (((clp_point_link->get_i32_xp()) == (clp_point->get_i32_xp())) && ((clp_point_link->get_i32_yp()) == (clp_point->get_i32_yp() + 1))) { - i_up_link_sw = ON; + i_up_link_sw = true; } /* 左につながっている */ if (((clp_point_link->get_i32_xp()) == (clp_point->get_i32_xp() - 1)) && ((clp_point_link->get_i32_yp()) == (clp_point->get_i32_yp()))) { - i_left_link_sw = ON; + i_left_link_sw = true; } /* 右につながっている */ if (((clp_point_link->get_i32_xp()) == (clp_point->get_i32_xp() + 1)) && ((clp_point_link->get_i32_yp()) == (clp_point->get_i32_yp()))) { - i_right_link_sw = ON; + i_right_link_sw = true; } } /* 左右両方につながりあるなら、斜めにはつなげず、次へ */ - if ((ON == i_left_link_sw) && (ON == i_right_link_sw)) continue; + if (i_left_link_sw && i_right_link_sw) continue; /* 上につながっているなら、斜めにはつなげず、次へ */ - if (ON == i_up_link_sw) continue; + if (i_up_link_sw) continue; for (clp_point2 = (pixel_point_node *)clp_point->get_clp_next(); (NULL != clp_point2) @@ -2978,7 +2957,7 @@ int pixel_line_root::_exec03_link_slant( } /* 左斜め上につながるものあり */ - if ((OFF == i_left_link_sw) && + if (!i_left_link_sw && ((clp_point2->get_i32_xp()) == (clp_point->get_i32_xp() - 1)) && ((clp_point2->get_i32_yp()) == (clp_point->get_i32_yp() + 1))) { /* 双方向リンクする */ @@ -2996,7 +2975,7 @@ int pixel_line_root::_exec03_link_slant( ++ii; } /* 右斜め上につながるものあり */ - if ((OFF == i_right_link_sw) && + if (!i_right_link_sw && ((clp_point2->get_i32_xp()) == (clp_point->get_i32_xp() + 1)) && ((clp_point2->get_i32_yp()) == (clp_point->get_i32_yp() + 1))) { /* 双方向リンクする */ @@ -3015,7 +2994,7 @@ int pixel_line_root::_exec03_link_slant( } } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" link slant %d", ii); } @@ -3027,7 +3006,7 @@ int pixel_line_root::_exec04_grouping(pixel_point_root *clp_pixel_point_root) { pixel_line_node *clp_line_before, *clp_line_crnt; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::_exec04_grouping()"); } @@ -3068,7 +3047,7 @@ int pixel_line_root::_exec04_grouping(pixel_point_root *clp_pixel_point_root) { } } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" make %d lines", this->get_i32_count()); } @@ -3083,7 +3062,7 @@ void pixel_line_root::exec05_set_middle(void) { pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec05_set_middle()"); } @@ -3094,7 +3073,7 @@ void pixel_line_root::exec05_set_middle(void) { clp_line->set_middle(); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" set middle point about %d lines", ii); } } @@ -3107,7 +3086,7 @@ void pixel_line_root::exec06_int2double_body(void) { pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec06_int2double_body()"); } @@ -3119,7 +3098,7 @@ void pixel_line_root::exec06_int2double_body(void) { clp_line->int2double_body(); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" int to double %d lines", ii); } } @@ -3131,16 +3110,16 @@ void pixel_line_root::exec07_smooth_body(void) { pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec07_smooth_body()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" smooth retry %u", this->_i32_smooth_retry); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(this->get_i32_count()); } @@ -3150,18 +3129,18 @@ void pixel_line_root::exec07_smooth_body(void) { assert(ii < this->get_i32_count()); /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(ii); } clp_line->smooth_body(this->_i32_smooth_retry); } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" smooth %d lines", ii); } } @@ -3170,15 +3149,15 @@ void pixel_line_root::exec10_smooth_expand(void) { pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec10_smooth_expand()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" smooth retry %u", this->_i32_smooth_retry); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(this->get_i32_count()); } @@ -3188,18 +3167,18 @@ void pixel_line_root::exec10_smooth_expand(void) { assert(ii < this->get_i32_count()); /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(ii); } clp_line->smooth_expand(this->_i32_smooth_retry); } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" smooth %d lines", ii); } } @@ -3213,7 +3192,7 @@ int pixel_line_root::exec08_expand_lines( pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec08_expand_lines()"); } @@ -3229,7 +3208,7 @@ int pixel_line_root::exec08_expand_lines( } } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" expand %d lines", ii); } @@ -3298,14 +3277,14 @@ void pixel_line_root::exec09_same_way_expand( int32_t i32_count_one, i32_count_another; /* 同方向曲げをしないときはここで抜けてしまう */ - if (ON != this->_i_same_way_exec_sw) { + if (!this->_i_same_way_exec_sw) { return; } - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec09_same_way_expand()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" select max length %g count %d", clp_select->get_d_length_max(), clp_select->get_i32_count_max()); @@ -3375,7 +3354,7 @@ void pixel_line_root::exec09_same_way_expand( clp_select->mem_free(); - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" same way expand one %d another %d", i32_count_one, i32_count_another); } @@ -3389,7 +3368,7 @@ void pixel_line_root::exec11_set_bbox(void) { pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec11_set_bbox()"); } @@ -3419,7 +3398,7 @@ void pixel_line_root::exec11_set_bbox(void) { } } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" set bbox %d lines : min x %g y %g : max x %g y %g", ii, this->_d_bbox_x_min, this->_d_bbox_y_min, this->_d_bbox_x_max, this->_d_bbox_y_max); @@ -3453,7 +3432,7 @@ void pixel_line_root::mem_free(void) { int32_t ii; if (NULL != this->get_clp_last()) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::mem_free()"); } @@ -3462,7 +3441,7 @@ void pixel_line_root::mem_free(void) { this->_remove(clp_); ++ii; } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("free line node %d", ii); } } @@ -3933,7 +3912,7 @@ public: this->clp_near_point = NULL; this->i32_near_point_pos = 0; this->d_length = -1.0; - this->i_reverse_sw = OFF; + this->i_reverse_sw = false; } void copy(pixel_select_curve_blur_node *clp) { this->clp_line = clp->clp_line; @@ -3948,7 +3927,7 @@ public: pixel_point_node *clp_near_point; int32_t i32_near_point_pos; double d_length; - int i_reverse_sw; + bool i_reverse_sw; private: }; @@ -3956,17 +3935,17 @@ private: class pixel_select_curve_blur_root final : public list_root { public: pixel_select_curve_blur_root(void) { - this->_i_mv_sw = OFF; - this->_i_cv_sw = OFF; - this->_i_pv_sw = OFF; + this->_i_mv_sw = false; + this->_i_cv_sw = false; + this->_i_pv_sw = false; this->_i32_count_max = 4; this->_d_length_max = 160; } ~pixel_select_curve_blur_root(void) { this->mem_free(); } - void set_i_mv_sw(int sw) { this->_i_mv_sw = sw; } - void set_i_cv_sw(int sw) { this->_i_cv_sw = sw; } - void set_i_pv_sw(int sw) { this->_i_pv_sw = sw; } + void set_i_mv_sw(bool sw) { this->_i_mv_sw = sw; } + void set_i_cv_sw(bool sw) { this->_i_cv_sw = sw; } + void set_i_pv_sw(bool sw) { this->_i_pv_sw = sw; } int32_t get_i32_count_max(void) { return this->_i32_count_max; } void set_i32_count_max(int32_t ii) { this->_i32_count_max = ii; } @@ -3986,7 +3965,7 @@ public: void mem_free(void); private: - int _i_mv_sw, _i_cv_sw, _i_pv_sw; + bool _i_mv_sw, _i_cv_sw, _i_pv_sw; int32_t _i32_count_max; double _d_length_max; @@ -4045,7 +4024,7 @@ void pixel_select_curve_blur_root::mem_free(void) { int32_t ii; if (NULL != this->get_clp_last()) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_select_curve_blur_root::mem_free()"); } @@ -4054,7 +4033,7 @@ void pixel_select_curve_blur_root::mem_free(void) { this->_remove((pixel_select_curve_blur_node *)this->get_clp_last()); ++ii; } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("free select curve blur node %d", ii); } } @@ -4107,7 +4086,7 @@ void pixel_select_curve_blur_root::exec(double d_xp, double d_yp, double d_effect_area_radius) { pixel_line_node *clp_line; int32_t ii, i32_pos; - int i_reverse_sw; + bool i_reverse_sw; pixel_point_node *clp_near_point, *clp_start_point; double d_length, d_radius, d_radius_1st; pixel_select_curve_blur_node cl_select; @@ -4170,7 +4149,7 @@ void pixel_select_curve_blur_root::exec(double d_xp, double d_yp, } /* 逆方向スイッチoffしておく */ - i_reverse_sw = OFF; + i_reverse_sw = false; /* 対応する部分のスタート点 */ clp_start_point = @@ -4197,7 +4176,7 @@ void pixel_select_curve_blur_root::exec(double d_xp, double d_yp, if ((M_PI / 2.0 < d_radius) && (d_radius < M_PI * 3.0 / 2.0)) { clp_start_point = clp_line->get_next_point_by_count(clp_near_point, i32_blur_count / 2); - i_reverse_sw = ON; + i_reverse_sw = true; } } @@ -4292,7 +4271,7 @@ int pixel_select_curve_blur_root::get_line(int32_t i32_blur_count, clp_point = clp_select->clp_start_point; /* 線分合成(いきなりの変化をへらす) */ - if (OFF == clp_select->i_reverse_sw) { + if (!clp_select->i_reverse_sw) { for (jj = 0; jj < i32_blur_count; ++jj) { dp_xv[jj] += (clp_point->get_d_xp_tgt() - d_xp) * d_ratio; dp_yv[jj] += (clp_point->get_d_yp_tgt() - d_yp) * d_ratio; @@ -4364,7 +4343,7 @@ int pixel_select_curve_blur_root::save(double d_xp, double d_yp, /* グループ(ライン)番号保存 */ if (fprintf(fp, "# selct number %d : reverse sw is %s\n", ii, - (OFF == clp_loop->i_reverse_sw) ? "off" : "on") < 0) { + (!clp_loop->i_reverse_sw ? "off" : "on")) < 0) { pri_funct_err_bttvr("Error : fprintf(# line number %d) returns minus", ii); fclose(fp); @@ -4386,7 +4365,7 @@ int pixel_select_curve_blur_root::save(double d_xp, double d_yp, } clp_point = clp_loop->clp_start_point; - if (OFF == clp_loop->i_reverse_sw) { + if (!clp_loop->i_reverse_sw) { for (jj = 0; jj < i32_blur_count; ++jj) { /* グループ(ライン)番号保存 */ if (fprintf(fp, "%g %g\n", clp_point->get_d_xp_tgt(), @@ -4446,19 +4425,12 @@ typedef unsigned short uint16_t; #define NG (-1) #endif -#ifndef ON -#define ON (1) -#endif -#ifndef OFF -#define OFF (0) -#endif - class thinnest_ui16_image { public: thinnest_ui16_image() { - this->_i_mv_sw = OFF; - this->_i_pv_sw = OFF; - this->_i_cv_sw = OFF; + this->_i_mv_sw = false; + this->_i_pv_sw = false; + this->_i_cv_sw = false; this->_i32_xs = 0; this->_i32_ys = 0; @@ -4474,9 +4446,9 @@ public: ~thinnest_ui16_image() { this->mem_free(); } /* パラメータ設定 */ - void set_i_mv_sw(int ii) { this->_i_mv_sw = ii; } - void set_i_pv_sw(int ii) { this->_i_pv_sw = ii; } - void set_i_cv_sw(int ii) { this->_i_cv_sw = ii; } + void set_i_mv_sw(bool ii) { this->_i_mv_sw = ii; } + void set_i_pv_sw(bool ii) { this->_i_pv_sw = ii; } + void set_i_cv_sw(bool ii) { this->_i_cv_sw = ii; } void set_i32_xs(int32_t ii) { this->_i32_xs = ii; } void set_i32_ys(int32_t ii) { this->_i32_ys = ii; } @@ -4511,9 +4483,9 @@ public: void mem_free(void); private: - int _i_mv_sw, /* Method Verbose */ - _i_pv_sw, /* Parameter Verbose */ - _i_cv_sw; /* Counter Verbose */ + bool _i_mv_sw; /* Method Verbose */ + bool _i_pv_sw; /* Parameter Verbose */ + bool _i_cv_sw; /* Counter Verbose */ int32_t _i32_xs, _i32_ys, /* Size */ _i32_xd, _i32_yd; /* sub Divide */ @@ -4565,11 +4537,11 @@ int32_t thinnest_ui16_image::exec01_fill_noise_pixel(void) { int32_t yy, i32_fill_count; /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::exec01_fill_noise_pixel()"); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(this->_i32_ys); } @@ -4582,7 +4554,7 @@ int32_t thinnest_ui16_image::exec01_fill_noise_pixel(void) { i32_fill_count = 0; for (yy = 0; yy < this->_i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(yy); } @@ -4600,7 +4572,7 @@ int32_t thinnest_ui16_image::exec01_fill_noise_pixel(void) { } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } @@ -4756,11 +4728,11 @@ void thinnest_ui16_image::exec02_scale_add_edge_pixel(void) { } /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::exec02_scale_add_edge_pixel()"); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(this->_i32_ys); } @@ -4770,7 +4742,7 @@ void thinnest_ui16_image::exec02_scale_add_edge_pixel(void) { /* 縁以外の部分のコピー */ for (yy = 0; yy < this->_i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(yy); } @@ -4783,7 +4755,7 @@ void thinnest_ui16_image::exec02_scale_add_edge_pixel(void) { ui16p_tgt1 += (this->_i32_xs + 2); } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } @@ -4902,14 +4874,14 @@ void thinnest_ui16_image::exec03_scale_liner(void) { } /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::exec03_scale_liner()"); } - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thi : Scale %d x %d", this->_i32_xd, this->_i32_yd); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start((this->_i32_ys - 2) * this->_i32_yd); } @@ -4923,7 +4895,7 @@ void thinnest_ui16_image::exec03_scale_liner(void) { for (yy = 0; yy < i32_tgt_ys; ++yy) { for (xx = 0; xx < i32_tgt_xs; ++xx, ++ui16p_tgt) { /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(yy); } @@ -5028,7 +5000,7 @@ void thinnest_ui16_image::exec03_scale_liner(void) { } } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } @@ -5048,15 +5020,15 @@ void thinnest_ui16_image::exec04_bw(void) { uint16_t *ui16p_src, *ui16p_tgt; /* 処理実行表示 */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::exec04_bw()"); } /* パラメータ表示 */ - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("thi : threshold %u", this->_ui16_threshold); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(this->_i32_ys); } @@ -5065,7 +5037,7 @@ void thinnest_ui16_image::exec04_bw(void) { for (yy = 0L; yy < this->_i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(yy); } @@ -5078,7 +5050,7 @@ void thinnest_ui16_image::exec04_bw(void) { } } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } @@ -5093,7 +5065,7 @@ int thinnest_ui16_image::exec05_thin(void) { i32_pixel_count_one_side_tmp, i32_pixel_count_one_side[4]; /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::exec05_thin()"); } @@ -5125,13 +5097,13 @@ int thinnest_ui16_image::exec05_thin(void) { this->_rot90_by_clockwork(); /* カウントダウン表示(上下左右ひとつずつピリオド表示) */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { (void)fprintf(stdout, "."); (void)fflush(stdout); } } /* カウントダウン表示(上下左右やって"....|"となる) */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { (void)fprintf(stdout, "|"); (void)fflush(stdout); /* 5 x 10カラムで改行 */ @@ -5144,12 +5116,12 @@ int thinnest_ui16_image::exec05_thin(void) { if (i32_pixel_count_one_round <= 0) break; } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { (void)fprintf(stdout, "\nthin line ... end.\n"); (void)fflush(stdout); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("thi : total %d loop, and %ld pixel deleted", ii, i32_pixel_count_total); pri_funct_msg_ttvr( @@ -5169,7 +5141,7 @@ int thinnest_ui16_image::exec05_thin(void) { void thinnest_ui16_image::mem_free(void) { #if 0 if (NULL != this->_ui16p_channel[0]) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr( "thinnest_ui16_image::mem_free()" ); } @@ -5179,7 +5151,7 @@ void thinnest_ui16_image::mem_free(void) { } #endif if (NULL != this->memory_free_this_) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::mem_free() <%x>", this->memory_free_this_); } @@ -5197,10 +5169,10 @@ int thinnest_ui16_image::mem_alloc(void) { this->mem_free(); /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::mem_alloc()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr( "alloc ui16_image memory (%d+%d) x (%d+%d) x %d x %d bytes", this->_i32_xs * this->_i32_xd, 2, this->_i32_ys * this->_i32_yd, 2, 2, @@ -5211,7 +5183,7 @@ int thinnest_ui16_image::mem_alloc(void) { (uint16_t *)calloc((this->_i32_xs * this->_i32_xd + 2) * (this->_i32_ys * this->_i32_yd + 2) * 2, sizeof(uint16_t)); - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::mem_alloc() memory <%x>", this->memory_free_this_); } @@ -5236,11 +5208,11 @@ int32_t thinnest_ui16_image::_one_side_thinner(void) { int32_t yy, i32_delete_count; /* 処理ごとのメッセージ */ - /******if (ON == this->_i_mv_sw) { + /******if (this->_i_mv_sw) { pri_funct_msg_ttvr( "thinnest_ui16_image::_one_side_thinner()" ); }******/ /* カウントダウン表示始め */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_start( this->_i32_ys ); } + // if (this->_i_cv_sw) { pri_funct_cv_start( this->_i32_ys ); } /* 始めのスキャンライン位置(画像から外れているものはNULLをいれる) */ ui16p_src_y1 = this->get_ui16p_src_channel() + this->_i32_xs; @@ -5252,7 +5224,7 @@ int32_t thinnest_ui16_image::_one_side_thinner(void) { i32_delete_count = 0; for (yy = 0; yy < this->_i32_ys; ++yy) { /* カウントダウン表示中 */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_run(yy); } + // if (this->_i_cv_sw) { pri_funct_cv_run(yy); } /* スキャンライン(とその前後のスキャンライン)毎の処理 */ i32_delete_count += this->_one_side_thinner_scanline( @@ -5269,7 +5241,7 @@ int32_t thinnest_ui16_image::_one_side_thinner(void) { } /* カウントダウン表示終了 */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_end(); } + // if (this->_i_cv_sw) { pri_funct_cv_end(); } /* 処理終了したらsrc,tgt画像交換 */ this->_swap_channel(); @@ -5368,7 +5340,7 @@ int32_t thinnest_ui16_image::_one_side_thinner_pixel( uint16_t *ui16p_tgt) { int32_t i32_delete_count; long l_off_count, l_white_count; - int i_sw, i_sw2; + bool i_sw, i_sw2; /* ui16p_src_x2bがNULLであってはならない */ assert(NULL != ui16p_src_x2b); @@ -5377,63 +5349,63 @@ int32_t thinnest_ui16_image::_one_side_thinner_pixel( i32_delete_count = 0; l_off_count = 0L; l_white_count = 0L; - i_sw = i_sw2 = OFF; + i_sw = i_sw2 = false; /* 時計回り(右回り)に見ていく */ /* 始め */ if (NULL != (ui16p_src_x1a)) { - i_sw = (0 < (*ui16p_src_x1a)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x1a); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } /* 次 ... */ if (NULL != (ui16p_src_x1b)) { - i_sw = (0 < (*ui16p_src_x1b)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x1b); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x1c)) { - i_sw = (0 < (*ui16p_src_x1c)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x1c); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x2c)) { - i_sw = (0 < (*ui16p_src_x2c)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x2c); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x3c)) { - i_sw = (0 < (*ui16p_src_x3c)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x3c); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x3b)) { - i_sw = (0 < (*ui16p_src_x3b)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x3b); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x3a)) { - i_sw = (0 < (*ui16p_src_x3a)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x3a); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x2a)) { - i_sw = (0 < (*ui16p_src_x2a)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x2a); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } /* 調査の開始点のみがゼロのときのため(l_off_count)開始点を再度調査する */ if (NULL != (ui16p_src_x1a)) { - i_sw = (0 < (*ui16p_src_x1a)) ? ON : OFF; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x1a); + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } @@ -5465,18 +5437,18 @@ void thinnest_ui16_image::_rot90_by_clockwork(void) { uint16_t *ui16p_src, *ui16p_tgt_y, *ui16p_tgt_x; /* 処理ごとのメッセージ */ - /******if (ON == this->_i_mv_sw) { + /******if (this->_i_mv_sw) { pri_funct_msg_ttvr( "thinnest_ui16_image::_rot90_by_clockwork()" ); }******/ /* カウントダウン表示始め */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_start( this->_i32_ys ); } + // if (this->_i_cv_sw) { pri_funct_cv_start( this->_i32_ys ); } ui16p_src = this->get_ui16p_src_channel(); ui16p_tgt_y = this->get_ui16p_tgt_channel() + (this->_i32_ys - 1); for (yy = 0L; yy < this->_i32_ys; ++yy) { /* カウントダウン表示中 */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_run(yy); } + // if (this->_i_cv_sw) { pri_funct_cv_run(yy); } ui16p_tgt_x = ui16p_tgt_y; for (xx = 0L; xx < this->_i32_xs; ++xx) { @@ -5487,7 +5459,7 @@ void thinnest_ui16_image::_rot90_by_clockwork(void) { --ui16p_tgt_y; } /* カウントダウン表示終了 */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_end(); } + // if (this->_i_cv_sw) { pri_funct_cv_end(); } /* 横と縦のサイズを交換 */ i32_tmp = this->_i32_xs; @@ -5652,7 +5624,8 @@ int igs_line_blur_brush_curve_blur_subpixel_( } int igs_line_blur_brush_curve_blur_all_( - int mv_sw, int pv_sw, int cv_sw, brush_curve_blur &cl_brush_curve_blur, + bool mv_sw, bool pv_sw, bool cv_sw, + brush_curve_blur &cl_brush_curve_blur, pixel_select_curve_blur_root &cl_pixel_select_curve_blur_root, pixel_line_root &cl_pixel_line_root @@ -5666,10 +5639,10 @@ int igs_line_blur_brush_curve_blur_all_( const int channels, const int bits, void *out // no_margin ) { /* 処理ごとのメッセージ */ - if (ON == mv_sw) { + if (mv_sw) { std::cout << "igs::line_blur::_brush_curve_blur_all()" << std::endl; } - if (ON == pv_sw) { + if (pv_sw) { std::cout << " curve blur points count is " << std::endl << cl_brush_curve_blur.get_i32_count() << std::endl << " power is " << std::endl @@ -5692,13 +5665,13 @@ int igs_line_blur_brush_curve_blur_all_( /* 画像をinからoutへコピーしておく */ (void)memcpy(out, in, height * width * channels * ((16 == bits) ? 2 : 1)); /* カウントダウン表示始め */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_start(height); } for (int yy = 0; yy < height; ++yy) { /* カウントダウン表示中 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_run(yy); } @@ -5719,7 +5692,7 @@ int igs_line_blur_brush_curve_blur_all_( } /* カウントダウン表示終了 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_end(); } @@ -5971,7 +5944,7 @@ void igs_line_blur_brush_smudge_line_( #include "igs_line_blur.h" // "pri.h" void igs_line_blur_brush_smudge_all_( - int mv_sw, int pv_sw, int cv_sw, + bool mv_sw, bool pv_sw, bool cv_sw, brush_smudge_circle &cl_brush_smudge_circle, pixel_line_root &cl_pixel_line_root, const void *in // no_margin , @@ -5982,11 +5955,11 @@ void igs_line_blur_brush_smudge_all_( const int channels, const int bits, void *out // no_margin ) { /* 処理ごとのメッセージ */ - if (ON == mv_sw) { + if (mv_sw) { std::cout << "igs::line_expand::_brush_smudge_all()" << std::endl; } - if (ON == pv_sw) { + if (pv_sw) { std::cout << " smudge ratio " << cl_brush_smudge_circle.get_d_ratio() << std::endl << " smudge brush size by pixel " @@ -6005,7 +5978,7 @@ void igs_line_blur_brush_smudge_all_( (void)memcpy(out, in, height * width * channels * ((16 == bits) ? 2 : 1)); /* カウントダウン表示始め */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_start(cl_pixel_line_root.get_i32_count()); } @@ -6020,7 +5993,7 @@ void igs_line_blur_brush_smudge_all_( } /* カウントダウン表示中 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_run(ii); } @@ -6028,7 +6001,7 @@ void igs_line_blur_brush_smudge_all_( channels, bits, out, clp_line); } /* カウントダウン表示終了 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_end(); } } @@ -6038,7 +6011,7 @@ void igs_line_blur_brush_smudge_all_( #include "igs_line_blur.h" // "pri.h" -void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, +void igs_line_blur_image_get_(const bool mv_sw, const bool cv_sw, const long reference_channel, thinnest_ui16_image &cl_thinnest_ui16_image @@ -6051,7 +6024,7 @@ void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, , const int channels, const int bits) { /* 処理ごとのメッセージ */ - if (ON == mv_sw) { + if (mv_sw) { std::cout << "igs_line_blur_image_get_()" << std::endl << "com : reference channel " << reference_channel << std::endl; } @@ -6061,7 +6034,7 @@ void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, unsigned short *out_incr = cl_thinnest_ui16_image.get_ui16p_src_channel(); /* カウントダウン表示始め */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_start(i32_ys); } @@ -6070,7 +6043,7 @@ void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, in_incr += reference_channel; for (int yy = 0; yy < i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_run(yy); } @@ -6089,7 +6062,7 @@ void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, for (int yy = 0; yy < i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_run(yy); } @@ -6105,7 +6078,7 @@ void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, } /* カウントダウン表示終了 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_end(); } } @@ -6154,15 +6127,15 @@ void igs::line_blur::convert( const int v_near_len /* min=2 def=160 incr=1 max=1000 */ , - const int mv_sw /* OFF */ + const bool mv_sw /* false=OFF */ , - const int pv_sw /* OFF */ + const bool pv_sw /* false=OFF */ , - const int cv_sw /* OFF */ + const bool cv_sw /* false=OFF */ , const long reference_channel /* 3 =Alpha:RGBA orBGRA */ , - const int debug_save_sw /* OFF */ + const bool debug_save_sw /* false=OFF */ , const int brush_action /* 0 =Curve Blur ,1=Smudge Brush */ ) { @@ -6195,7 +6168,7 @@ void igs::line_blur::convert( cl_brush_curve_blur.set_i_cv_sw(cv_sw); /* --- 処理ごとのメッセージ --- */ - if (ON == mv_sw) { + if (mv_sw) { std::cout << "igs::line_blur::convert()" << std::endl; } @@ -6210,7 +6183,7 @@ void igs::line_blur::convert( this->set_e_brush_smudge_action(); } else { this->set_e_brush_curve_blur_action(); - cl_pixel_line_root.set_i_same_way_exec_sw(OFF); + cl_pixel_line_root.set_i_same_way_exec_sw(false); }******/ /* 1: $b_blur_count :Wheel(min=1, default=51, increment=1, max=100) */ @@ -6294,7 +6267,7 @@ void igs::line_blur::convert( throw std::domain_error( "Error : cl_pixel_line_root.exec01020304() returns NG"); } - if (ON == debug_save_sw) { + if (debug_save_sw) { if (OK != cl_pixel_line_root.save_lines("tmp08_jaggy_lines.txt")) { throw std::domain_error( "Error : cl_pixel_line_root.save_lines(-) returns NG"); @@ -6318,7 +6291,7 @@ void igs::line_blur::convert( /* 中点をセットする */ cl_pixel_line_root.exec05_set_middle(); - if (ON == debug_save_sw) { + if (debug_save_sw) { if (OK != cl_pixel_line_root.save_middle_point("tmp12_middle_point.txt")) { throw std::domain_error( "Error : cl_pixel_line_root.save_middle_point(-) returns NG"); @@ -6338,7 +6311,7 @@ void igs::line_blur::convert( } /* 伸ばした線分の方向をそろえる */ - if (ON == debug_save_sw) { + if (debug_save_sw) { if (OK != cl_pixel_line_root.save_expand_vector("tmp13_expand_vector.txt")) { throw std::domain_error( @@ -6346,7 +6319,7 @@ void igs::line_blur::convert( } } cl_pixel_line_root.exec09_same_way_expand(&(cl_pixel_select_same_way_root)); - if (ON == debug_save_sw) { + if (debug_save_sw) { if (OK != cl_pixel_line_root.save_expand_vector("tmp14_same_way_vector.txt")) { throw std::domain_error( @@ -6357,7 +6330,7 @@ void igs::line_blur::convert( /* 伸ばした線分を再度スムースに */ cl_pixel_line_root.exec10_smooth_expand(); - if (ON == debug_save_sw) { + if (debug_save_sw) { if (OK != cl_pixel_line_root.save_expand_lines("tmp15_expand_lines.txt")) { throw std::domain_error( "Error : cl_pixel_line_root.save_expand_lines(-) returns NG"); diff --git a/toonz/sources/stdfx/igs_line_blur.h b/toonz/sources/stdfx/igs_line_blur.h index d9f0ee3..f857754 100644 --- a/toonz/sources/stdfx/igs_line_blur.h +++ b/toonz/sources/stdfx/igs_line_blur.h @@ -48,15 +48,15 @@ IGS_LINE_BLUR_EXPORT void convert( const int v_near_len /* min=2 def=160 incr=1 max=1000 */ , - const int mv_sw /* 0 =OFF */ + const bool mv_sw /* false=OFF */ , - const int pv_sw /* 0 =OFF */ + const bool pv_sw /* false=OFF */ , - const int cv_sw /* 0 =OFF */ + const bool cv_sw /* false=OFF */ , const long reference_channel /* 3 =Alpha:RGBA orBGRA */ , - const int debug_save_sw /* 0 =OFF */ + const bool debug_save_sw /* false=OFF */ , const int brush_action /* 0 =Curve Blur ,1=Smudge Brush */ ); diff --git a/toonz/sources/stdfx/ino_line_blur.cpp b/toonz/sources/stdfx/ino_line_blur.cpp index 95c87f9..6df5675 100644 --- a/toonz/sources/stdfx/ino_line_blur.cpp +++ b/toonz/sources/stdfx/ino_line_blur.cpp @@ -48,15 +48,15 @@ IGS_LINE_BLUR_EXPORT void convert( const int v_near_len /* min=2 def=160 incr=1 max=1000 */ , - const int mv_sw /* 0 =OFF */ + const bool mv_sw /* false=OFF */ , - const int pv_sw /* 0 =OFF */ + const bool pv_sw /* false=OFF */ , - const int cv_sw /* 0 =OFF */ + const bool cv_sw /* false=OFF */ , const long reference_channel /* 3 =Alpha:RGBA orBGRA */ , - const int debug_save_sw /* 0 =OFF */ + const bool debug_save_sw /* false=OFF */ , const int brush_action /* 0 =Curve Blur ,1=Smudge Brush */ ); @@ -390,13 +390,6 @@ typedef int int32_t; #include /* for int32_t */ #endif -#ifndef ON -#define ON (1) -#endif -#ifndef OFF -#define OFF (0) -#endif - #ifndef OK #define OK (0) #endif @@ -414,9 +407,9 @@ public: brush_curve_blur(void) { int32_t ii; - this->_i_mv_sw = OFF; - this->_i_pv_sw = OFF; - this->_i_cv_sw = OFF; + this->_i_mv_sw = false; + this->_i_pv_sw = false; + this->_i_cv_sw = false; this->_i32_count = 51; this->_i32_subpixel_divide = 2; @@ -436,9 +429,9 @@ public: ~brush_curve_blur(void) { this->mem_free(); } /* パラメータ設定 */ - void set_i_mv_sw(int ii) { this->_i_mv_sw = ii; } - void set_i_pv_sw(int ii) { this->_i_pv_sw = ii; } - void set_i_cv_sw(int ii) { this->_i_cv_sw = ii; } + void set_i_mv_sw(bool ii) { this->_i_mv_sw = ii; } + void set_i_pv_sw(bool ii) { this->_i_pv_sw = ii; } + void set_i_cv_sw(bool ii) { this->_i_cv_sw = ii; } /* ぼかし線のポイント数 */ void set_i32_count(int32_t ii) { this->_i32_count = ii; } @@ -469,9 +462,9 @@ public: void debug_print(void); private: - int _i_mv_sw, /* Method Verbose */ - _i_pv_sw, /* Parameter Verbose */ - _i_cv_sw; /* Counter Verbose */ + bool _i_mv_sw; /* Method Verbose */ + bool _i_pv_sw; /* Parameter Verbose */ + bool _i_cv_sw; /* Counter Verbose */ int32_t _i32_count; int32_t _i32_subpixel_divide; @@ -491,7 +484,7 @@ private: /* メモリ開放 */ void brush_curve_blur::mem_free(void) { if (NULL != this->_dp_ratio) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("brush_curve_blur::mem_free()"); } free(this->_dp_ratio); @@ -514,10 +507,10 @@ int brush_curve_blur::mem_alloc(void) { } /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("brush_curve_blur::mem_alloc()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr( "alloc brush_curve_blur memory ((%d * %d) + %d) x %d bytes", this->_i32_count, (1 + CHANNEL_COUNT + 2), /* ratio,accum,xp,yp */ @@ -706,13 +699,6 @@ typedef unsigned short uint16_t; #include /* for int32_t, uint16_t */ #endif -#ifndef ON -#define ON (1) -#endif -#ifndef OFF -#define OFF (0) -#endif - #ifndef OK #define OK (0) #endif @@ -723,9 +709,9 @@ typedef unsigned short uint16_t; class brush_smudge_circle { public: brush_smudge_circle() { - this->_i_mv_sw = OFF; - this->_i_pv_sw = OFF; - this->_i_cv_sw = OFF; + this->_i_mv_sw = false; + this->_i_pv_sw = false; + this->_i_cv_sw = false; this->_i32_size_by_pixel = 7; /* 画像上の線の最大幅 */ this->_i32_subpixel_divide = 4; @@ -738,9 +724,9 @@ public: ~brush_smudge_circle() { this->mem_free(); } /* パラメータ設定 */ - void set_i_mv_sw(int ii) { this->_i_mv_sw = ii; } - void set_i_pv_sw(int ii) { this->_i_pv_sw = ii; } - void set_i_cv_sw(int ii) { this->_i_cv_sw = ii; } + void set_i_mv_sw(bool ii) { this->_i_mv_sw = ii; } + void set_i_pv_sw(bool ii) { this->_i_pv_sw = ii; } + void set_i_cv_sw(bool ii) { this->_i_cv_sw = ii; } void set_i32_size_by_pixel(int32_t ii) { this->_i32_size_by_pixel = ii; } void set_i32_subpixel_divide(int32_t ii) { this->_i32_subpixel_divide = ii; } @@ -796,7 +782,7 @@ private: /* メモリ開放 */ void brush_smudge_circle::mem_free(void) { if (NULL != this->_dp_brush) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("brush_smudge_circle::mem_free()"); } free(this->_dp_brush); @@ -817,11 +803,11 @@ int brush_smudge_circle::mem_alloc(void) { i32_sz = this->_i32_size_by_pixel * this->_i32_subpixel_divide; /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("brush_smudge_circle::mem_alloc()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("calloc((%d x %d + %d x %d + %d x %d) x (%d x %d))", i32_sz, i32_sz, i32_sz, i32_sz, (this->_i32_size_by_pixel + 1), @@ -1346,25 +1332,18 @@ void pixel_point_node::print_xy_around(void) { #include "igs_line_blur.h" // "list_root.h" "pixel_point_node.h" -#ifndef ON -#define ON (1) -#endif -#ifndef OFF -#define OFF (0) -#endif - class pixel_point_root final : public list_root { public: pixel_point_root(void) { - this->_i_mv_sw = OFF; - this->_i_cv_sw = OFF; - this->_i_pv_sw = OFF; + this->_i_mv_sw = false; + this->_i_cv_sw = false; + this->_i_pv_sw = false; } ~pixel_point_root(void) { this->mem_free(); } - void set_i_mv_sw(int sw) { this->_i_mv_sw = sw; } - void set_i_cv_sw(int sw) { this->_i_cv_sw = sw; } - void set_i_pv_sw(int sw) { this->_i_pv_sw = sw; } + void set_i_mv_sw(bool sw) { this->_i_mv_sw = sw; } + void set_i_cv_sw(bool sw) { this->_i_cv_sw = sw; } + void set_i_pv_sw(bool sw) { this->_i_pv_sw = sw; } /* 16Bits 1channel画像からゼロ以上のピクセルをプロットする */ int alloc_mem_and_list_node(int32_t i32_xs, int32_t i32_ys, @@ -1379,7 +1358,7 @@ public: void mem_free(void); private: - int _i_mv_sw, _i_cv_sw, _i_pv_sw; + bool _i_mv_sw, _i_cv_sw, _i_pv_sw; /* リストの削除 */ void _remove(pixel_point_node *clp_target); @@ -1414,7 +1393,7 @@ void pixel_point_root::mem_free(void) { int32_t ii; if (NULL != this->get_clp_last()) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_point_root::mem_free()"); } ii = 0; @@ -1422,7 +1401,7 @@ void pixel_point_root::mem_free(void) { this->_remove(clp_); ++ii; } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("free point node %d", ii); } } @@ -1434,19 +1413,19 @@ int pixel_point_root::alloc_mem_and_list_node(int32_t i32_xs, int32_t i32_ys, pixel_point_node *clp_pp; /* 処理実行表示 */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_point_root::alloc_mem_and_list_node()"); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(i32_ys); } clp_pp = NULL; for (yy = 0; yy < i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(yy); } @@ -1463,12 +1442,12 @@ int pixel_point_root::alloc_mem_and_list_node(int32_t i32_xs, int32_t i32_ys, } } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } /* 処理結果表示 */ - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("alloc and list %d points", this->get_i32_count()); } @@ -2490,17 +2469,17 @@ private: class pixel_select_same_way_root final : public list_root { public: pixel_select_same_way_root(void) { - this->_i_mv_sw = OFF; - this->_i_cv_sw = OFF; - this->_i_pv_sw = OFF; + this->_i_mv_sw = false; + this->_i_cv_sw = false; + this->_i_pv_sw = false; this->_i32_count_max = 4; this->_d_length_max = 160; } ~pixel_select_same_way_root(void) { this->mem_free(); } - void set_i_mv_sw(int sw) { this->_i_mv_sw = sw; } - void set_i_cv_sw(int sw) { this->_i_cv_sw = sw; } - void set_i_pv_sw(int sw) { this->_i_pv_sw = sw; } + void set_i_mv_sw(bool sw) { this->_i_mv_sw = sw; } + void set_i_cv_sw(bool sw) { this->_i_cv_sw = sw; } + void set_i_pv_sw(bool sw) { this->_i_pv_sw = sw; } int32_t get_i32_count_max(void) { return this->_i32_count_max; } void set_i32_count_max(int32_t ii) { this->_i32_count_max = ii; } @@ -2516,7 +2495,7 @@ public: void mem_free(void); private: - int _i_mv_sw, _i_cv_sw, _i_pv_sw; + bool _i_mv_sw, _i_cv_sw, _i_pv_sw; int32_t _i32_count_max; double _d_length_max; @@ -2571,7 +2550,7 @@ void pixel_select_same_way_root::mem_free(void) { int32_t ii; if (NULL != this->get_clp_last()) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_select_same_way_root::mem_free()"); } @@ -2581,7 +2560,7 @@ void pixel_select_same_way_root::mem_free(void) { this->_remove(clp_); ++ii; } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("free select same way node %d", ii); } } @@ -2786,9 +2765,9 @@ void pixel_select_same_way_root::get_vector(double *dp_xv, double *dp_yv) { class pixel_line_root final : public list_root { public: pixel_line_root(void) { - this->_i_mv_sw = OFF; - this->_i_cv_sw = OFF; - this->_i_pv_sw = OFF; + this->_i_mv_sw = false; + this->_i_cv_sw = false; + this->_i_pv_sw = false; this->_d_bbox_x_min = 0.0; this->_d_bbox_x_max = 0.0; @@ -2796,12 +2775,12 @@ public: this->_d_bbox_y_max = 0.0; this->_i32_smooth_retry = 100; - this->_i_same_way_exec_sw = ON; + this->_i_same_way_exec_sw = true; } ~pixel_line_root(void) { this->mem_free(); } - void set_i_mv_sw(int sw) { this->_i_mv_sw = sw; } - void set_i_cv_sw(int sw) { this->_i_cv_sw = sw; } - void set_i_pv_sw(int sw) { this->_i_pv_sw = sw; } + void set_i_mv_sw(bool sw) { this->_i_mv_sw = sw; } + void set_i_cv_sw(bool sw) { this->_i_cv_sw = sw; } + void set_i_pv_sw(bool sw) { this->_i_pv_sw = sw; } double get_d_bbox_x_min(void) { return this->_d_bbox_x_min; } double get_d_bbox_x_max(void) { return this->_d_bbox_x_max; } @@ -2810,7 +2789,7 @@ public: void set_i32_smooth_retry(int32_t i32) { this->_i32_smooth_retry = i32; } int32_t get_i32_smooth_retry(void) { return this->_i32_smooth_retry; } - void set_i_same_way_exec_sw(int sw) { this->_i_same_way_exec_sw = sw; } + void set_i_same_way_exec_sw(bool sw) { this->_i_same_way_exec_sw = sw; } int exec01020304(pixel_point_root *clp_pixel_point_root); void exec05_set_middle(void); @@ -2836,12 +2815,12 @@ public: void mem_free(void); private: - int _i_mv_sw, _i_cv_sw, _i_pv_sw; + bool _i_mv_sw, _i_cv_sw, _i_pv_sw; double _d_bbox_x_min, _d_bbox_x_max, _d_bbox_y_min, _d_bbox_y_max; int32_t _i32_smooth_retry; - int _i_same_way_exec_sw; + bool _i_same_way_exec_sw; calculator_geometry _cl_cal_geom; @@ -2895,7 +2874,7 @@ int pixel_line_root::_exec01_link_left_right( pixel_point_node *clp_point, *clp_point2; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::_exec01_link_left_right()"); } @@ -2926,7 +2905,7 @@ int pixel_line_root::_exec01_link_left_right( clp_point2 = clp_point; } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" link left right %d", ii); } @@ -2937,7 +2916,7 @@ int pixel_line_root::_exec02_link_up_down( pixel_point_node *clp_point, *clp_point2; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::_exec02_link_up_down()"); } @@ -2975,7 +2954,7 @@ int pixel_line_root::_exec02_link_up_down( } } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" link up down %d", ii); } @@ -2987,9 +2966,9 @@ int pixel_line_root::_exec03_link_slant( pixel_point_node *clp_point, *clp_point2, *clp_point_link; int32_t ii, jj; - int i_left_link_sw, i_right_link_sw, i_up_link_sw; + bool i_left_link_sw, i_right_link_sw, i_up_link_sw; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::_exec03_link_slant()"); } @@ -3004,9 +2983,9 @@ int pixel_line_root::_exec03_link_slant( continue; } - i_left_link_sw = OFF; - i_right_link_sw = OFF; - i_up_link_sw = OFF; + i_left_link_sw = false; + i_right_link_sw = false; + i_up_link_sw = false; /* 全リンクの調査 */ for (jj = 0; jj < LINK_NEAR_COUNT; ++jj) { @@ -3016,24 +2995,24 @@ int pixel_line_root::_exec03_link_slant( /* 上につながっている */ if (((clp_point_link->get_i32_xp()) == (clp_point->get_i32_xp())) && ((clp_point_link->get_i32_yp()) == (clp_point->get_i32_yp() + 1))) { - i_up_link_sw = ON; + i_up_link_sw = true; } /* 左につながっている */ if (((clp_point_link->get_i32_xp()) == (clp_point->get_i32_xp() - 1)) && ((clp_point_link->get_i32_yp()) == (clp_point->get_i32_yp()))) { - i_left_link_sw = ON; + i_left_link_sw = true; } /* 右につながっている */ if (((clp_point_link->get_i32_xp()) == (clp_point->get_i32_xp() + 1)) && ((clp_point_link->get_i32_yp()) == (clp_point->get_i32_yp()))) { - i_right_link_sw = ON; + i_right_link_sw = true; } } /* 左右両方につながりあるなら、斜めにはつなげず、次へ */ - if ((ON == i_left_link_sw) && (ON == i_right_link_sw)) continue; + if (i_left_link_sw && i_right_link_sw) continue; /* 上につながっているなら、斜めにはつなげず、次へ */ - if (ON == i_up_link_sw) continue; + if (i_up_link_sw) continue; for (clp_point2 = (pixel_point_node *)clp_point->get_clp_next(); (NULL != clp_point2) @@ -3046,7 +3025,7 @@ int pixel_line_root::_exec03_link_slant( } /* 左斜め上につながるものあり */ - if ((OFF == i_left_link_sw) && + if (!i_left_link_sw && ((clp_point2->get_i32_xp()) == (clp_point->get_i32_xp() - 1)) && ((clp_point2->get_i32_yp()) == (clp_point->get_i32_yp() + 1))) { /* 双方向リンクする */ @@ -3064,7 +3043,7 @@ int pixel_line_root::_exec03_link_slant( ++ii; } /* 右斜め上につながるものあり */ - if ((OFF == i_right_link_sw) && + if (!i_right_link_sw && ((clp_point2->get_i32_xp()) == (clp_point->get_i32_xp() + 1)) && ((clp_point2->get_i32_yp()) == (clp_point->get_i32_yp() + 1))) { /* 双方向リンクする */ @@ -3083,7 +3062,7 @@ int pixel_line_root::_exec03_link_slant( } } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" link slant %d", ii); } @@ -3095,7 +3074,7 @@ int pixel_line_root::_exec04_grouping(pixel_point_root *clp_pixel_point_root) { pixel_line_node *clp_line_before, *clp_line_crnt; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::_exec04_grouping()"); } @@ -3136,7 +3115,7 @@ int pixel_line_root::_exec04_grouping(pixel_point_root *clp_pixel_point_root) { } } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" make %d lines", this->get_i32_count()); } @@ -3151,7 +3130,7 @@ void pixel_line_root::exec05_set_middle(void) { pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec05_set_middle()"); } @@ -3162,7 +3141,7 @@ void pixel_line_root::exec05_set_middle(void) { clp_line->set_middle(); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" set middle point about %d lines", ii); } } @@ -3175,7 +3154,7 @@ void pixel_line_root::exec06_int2double_body(void) { pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec06_int2double_body()"); } @@ -3187,7 +3166,7 @@ void pixel_line_root::exec06_int2double_body(void) { clp_line->int2double_body(); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" int to double %d lines", ii); } } @@ -3199,16 +3178,16 @@ void pixel_line_root::exec07_smooth_body(void) { pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec07_smooth_body()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" smooth retry %u", this->_i32_smooth_retry); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(this->get_i32_count()); } @@ -3218,18 +3197,18 @@ void pixel_line_root::exec07_smooth_body(void) { assert(ii < this->get_i32_count()); /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(ii); } clp_line->smooth_body(this->_i32_smooth_retry); } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" smooth %d lines", ii); } } @@ -3238,15 +3217,15 @@ void pixel_line_root::exec10_smooth_expand(void) { pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec10_smooth_expand()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" smooth retry %u", this->_i32_smooth_retry); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(this->get_i32_count()); } @@ -3256,18 +3235,18 @@ void pixel_line_root::exec10_smooth_expand(void) { assert(ii < this->get_i32_count()); /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(ii); } clp_line->smooth_expand(this->_i32_smooth_retry); } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" smooth %d lines", ii); } } @@ -3281,7 +3260,7 @@ int pixel_line_root::exec08_expand_lines( pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec08_expand_lines()"); } @@ -3297,7 +3276,7 @@ int pixel_line_root::exec08_expand_lines( } } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" expand %d lines", ii); } @@ -3366,14 +3345,14 @@ void pixel_line_root::exec09_same_way_expand( int32_t i32_count_one, i32_count_another; /* 同方向曲げをしないときはここで抜けてしまう */ - if (ON != this->_i_same_way_exec_sw) { + if (!this->_i_same_way_exec_sw) { return; } - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec09_same_way_expand()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" select max length %g count %d", clp_select->get_d_length_max(), clp_select->get_i32_count_max()); @@ -3443,7 +3422,7 @@ void pixel_line_root::exec09_same_way_expand( clp_select->mem_free(); - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" same way expand one %d another %d", i32_count_one, i32_count_another); } @@ -3457,7 +3436,7 @@ void pixel_line_root::exec11_set_bbox(void) { pixel_line_node *clp_line; int32_t ii; - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::exec11_set_bbox()"); } @@ -3487,7 +3466,7 @@ void pixel_line_root::exec11_set_bbox(void) { } } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr(" set bbox %d lines : min x %g y %g : max x %g y %g", ii, this->_d_bbox_x_min, this->_d_bbox_y_min, this->_d_bbox_x_max, this->_d_bbox_y_max); @@ -3521,7 +3500,7 @@ void pixel_line_root::mem_free(void) { int32_t ii; if (NULL != this->get_clp_last()) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_line_root::mem_free()"); } @@ -3530,7 +3509,7 @@ void pixel_line_root::mem_free(void) { this->_remove(clp_); ++ii; } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("free line node %d", ii); } } @@ -4001,7 +3980,7 @@ public: this->clp_near_point = NULL; this->i32_near_point_pos = 0; this->d_length = -1.0; - this->i_reverse_sw = OFF; + this->i_reverse_sw = false; } void copy(pixel_select_curve_blur_node *clp) { this->clp_line = clp->clp_line; @@ -4016,7 +3995,7 @@ public: pixel_point_node *clp_near_point; int32_t i32_near_point_pos; double d_length; - int i_reverse_sw; + bool i_reverse_sw; private: }; @@ -4024,17 +4003,17 @@ private: class pixel_select_curve_blur_root final : public list_root { public: pixel_select_curve_blur_root(void) { - this->_i_mv_sw = OFF; - this->_i_cv_sw = OFF; - this->_i_pv_sw = OFF; + this->_i_mv_sw = false; + this->_i_cv_sw = false; + this->_i_pv_sw = false; this->_i32_count_max = 4; this->_d_length_max = 160; } ~pixel_select_curve_blur_root(void) { this->mem_free(); } - void set_i_mv_sw(int sw) { this->_i_mv_sw = sw; } - void set_i_cv_sw(int sw) { this->_i_cv_sw = sw; } - void set_i_pv_sw(int sw) { this->_i_pv_sw = sw; } + void set_i_mv_sw(bool sw) { this->_i_mv_sw = sw; } + void set_i_cv_sw(bool sw) { this->_i_cv_sw = sw; } + void set_i_pv_sw(bool sw) { this->_i_pv_sw = sw; } int32_t get_i32_count_max(void) { return this->_i32_count_max; } void set_i32_count_max(int32_t ii) { this->_i32_count_max = ii; } @@ -4054,7 +4033,7 @@ public: void mem_free(void); private: - int _i_mv_sw, _i_cv_sw, _i_pv_sw; + bool _i_mv_sw, _i_cv_sw, _i_pv_sw; int32_t _i32_count_max; double _d_length_max; @@ -4113,7 +4092,7 @@ void pixel_select_curve_blur_root::mem_free(void) { int32_t ii; if (NULL != this->get_clp_last()) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("pixel_select_curve_blur_root::mem_free()"); } @@ -4122,7 +4101,7 @@ void pixel_select_curve_blur_root::mem_free(void) { this->_remove((pixel_select_curve_blur_node *)this->get_clp_last()); ++ii; } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("free select curve blur node %d", ii); } } @@ -4175,7 +4154,7 @@ void pixel_select_curve_blur_root::exec(double d_xp, double d_yp, double d_effect_area_radius) { pixel_line_node *clp_line; int32_t ii, i32_pos; - int i_reverse_sw; + bool i_reverse_sw; pixel_point_node *clp_near_point, *clp_start_point; double d_length, d_radius, d_radius_1st; pixel_select_curve_blur_node cl_select; @@ -4238,7 +4217,7 @@ void pixel_select_curve_blur_root::exec(double d_xp, double d_yp, } /* 逆方向スイッチoffしておく */ - i_reverse_sw = OFF; + i_reverse_sw = false; /* 対応する部分のスタート点 */ clp_start_point = @@ -4265,7 +4244,7 @@ void pixel_select_curve_blur_root::exec(double d_xp, double d_yp, if ((M_PI / 2.0 < d_radius) && (d_radius < M_PI * 3.0 / 2.0)) { clp_start_point = clp_line->get_next_point_by_count(clp_near_point, i32_blur_count / 2); - i_reverse_sw = ON; + i_reverse_sw = true; } } @@ -4360,7 +4339,7 @@ int pixel_select_curve_blur_root::get_line(int32_t i32_blur_count, clp_point = clp_select->clp_start_point; /* 線分合成(いきなりの変化をへらす) */ - if (OFF == clp_select->i_reverse_sw) { + if (!clp_select->i_reverse_sw) { for (jj = 0; jj < i32_blur_count; ++jj) { dp_xv[jj] += (clp_point->get_d_xp_tgt() - d_xp) * d_ratio; dp_yv[jj] += (clp_point->get_d_yp_tgt() - d_yp) * d_ratio; @@ -4432,7 +4411,7 @@ int pixel_select_curve_blur_root::save(double d_xp, double d_yp, /* グループ(ライン)番号保存 */ if (fprintf(fp, "# selct number %d : reverse sw is %s\n", ii, - (OFF == clp_loop->i_reverse_sw) ? "off" : "on") < 0) { + (!clp_loop->i_reverse_sw ? "off" : "on")) < 0) { pri_funct_err_bttvr("Error : fprintf(# line number %d) returns minus", ii); fclose(fp); @@ -4454,7 +4433,7 @@ int pixel_select_curve_blur_root::save(double d_xp, double d_yp, } clp_point = clp_loop->clp_start_point; - if (OFF == clp_loop->i_reverse_sw) { + if (!clp_loop->i_reverse_sw) { for (jj = 0; jj < i32_blur_count; ++jj) { /* グループ(ライン)番号保存 */ if (fprintf(fp, "%g %g\n", clp_point->get_d_xp_tgt(), @@ -4514,19 +4493,12 @@ typedef unsigned short uint16_t; #define NG (-1) #endif -#ifndef ON -#define ON (1) -#endif -#ifndef OFF -#define OFF (0) -#endif - class thinnest_ui16_image { public: thinnest_ui16_image() { - this->_i_mv_sw = OFF; - this->_i_pv_sw = OFF; - this->_i_cv_sw = OFF; + this->_i_mv_sw = false; + this->_i_pv_sw = false; + this->_i_cv_sw = false; this->_i32_xs = 0; this->_i32_ys = 0; @@ -4542,9 +4514,9 @@ public: ~thinnest_ui16_image() { this->mem_free(); } /* パラメータ設定 */ - void set_i_mv_sw(int ii) { this->_i_mv_sw = ii; } - void set_i_pv_sw(int ii) { this->_i_pv_sw = ii; } - void set_i_cv_sw(int ii) { this->_i_cv_sw = ii; } + void set_i_mv_sw(bool ii) { this->_i_mv_sw = ii; } + void set_i_pv_sw(bool ii) { this->_i_pv_sw = ii; } + void set_i_cv_sw(bool ii) { this->_i_cv_sw = ii; } void set_i32_xs(int32_t ii) { this->_i32_xs = ii; } void set_i32_ys(int32_t ii) { this->_i32_ys = ii; } @@ -4579,9 +4551,9 @@ public: void mem_free(void); private: - int _i_mv_sw, /* Method Verbose */ - _i_pv_sw, /* Parameter Verbose */ - _i_cv_sw; /* Counter Verbose */ + bool _i_mv_sw; /* Method Verbose */ + bool _i_pv_sw; /* Parameter Verbose */ + bool _i_cv_sw; /* Counter Verbose */ int32_t _i32_xs, _i32_ys, /* Size */ _i32_xd, _i32_yd; /* sub Divide */ @@ -4633,11 +4605,11 @@ int32_t thinnest_ui16_image::exec01_fill_noise_pixel(void) { int32_t yy, i32_fill_count; /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::exec01_fill_noise_pixel()"); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(this->_i32_ys); } @@ -4650,7 +4622,7 @@ int32_t thinnest_ui16_image::exec01_fill_noise_pixel(void) { i32_fill_count = 0; for (yy = 0; yy < this->_i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(yy); } @@ -4668,7 +4640,7 @@ int32_t thinnest_ui16_image::exec01_fill_noise_pixel(void) { } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } @@ -4824,11 +4796,11 @@ void thinnest_ui16_image::exec02_scale_add_edge_pixel(void) { } /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::exec02_scale_add_edge_pixel()"); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(this->_i32_ys); } @@ -4838,7 +4810,7 @@ void thinnest_ui16_image::exec02_scale_add_edge_pixel(void) { /* 縁以外の部分のコピー */ for (yy = 0; yy < this->_i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(yy); } @@ -4851,7 +4823,7 @@ void thinnest_ui16_image::exec02_scale_add_edge_pixel(void) { ui16p_tgt1 += (this->_i32_xs + 2); } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } @@ -4970,14 +4942,14 @@ void thinnest_ui16_image::exec03_scale_liner(void) { } /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::exec03_scale_liner()"); } - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thi : Scale %d x %d", this->_i32_xd, this->_i32_yd); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start((this->_i32_ys - 2) * this->_i32_yd); } @@ -4991,7 +4963,7 @@ void thinnest_ui16_image::exec03_scale_liner(void) { for (yy = 0; yy < i32_tgt_ys; ++yy) { for (xx = 0; xx < i32_tgt_xs; ++xx, ++ui16p_tgt) { /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(yy); } @@ -5096,7 +5068,7 @@ void thinnest_ui16_image::exec03_scale_liner(void) { } } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } @@ -5116,15 +5088,15 @@ void thinnest_ui16_image::exec04_bw(void) { uint16_t *ui16p_src, *ui16p_tgt; /* 処理実行表示 */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::exec04_bw()"); } /* パラメータ表示 */ - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("thi : threshold %u", this->_ui16_threshold); } /* カウントダウン表示始め */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_start(this->_i32_ys); } @@ -5133,7 +5105,7 @@ void thinnest_ui16_image::exec04_bw(void) { for (yy = 0L; yy < this->_i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_run(yy); } @@ -5146,7 +5118,7 @@ void thinnest_ui16_image::exec04_bw(void) { } } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { pri_funct_cv_end(); } @@ -5161,7 +5133,7 @@ int thinnest_ui16_image::exec05_thin(void) { i32_pixel_count_one_side_tmp, i32_pixel_count_one_side[4]; /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::exec05_thin()"); } @@ -5193,13 +5165,13 @@ int thinnest_ui16_image::exec05_thin(void) { this->_rot90_by_clockwork(); /* カウントダウン表示(上下左右ひとつずつピリオド表示) */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { (void)fprintf(stdout, "."); (void)fflush(stdout); } } /* カウントダウン表示(上下左右やって"....|"となる) */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { (void)fprintf(stdout, "|"); (void)fflush(stdout); /* 5 x 10カラムで改行 */ @@ -5212,12 +5184,12 @@ int thinnest_ui16_image::exec05_thin(void) { if (i32_pixel_count_one_round <= 0) break; } /* カウントダウン表示終了 */ - if (ON == this->_i_cv_sw) { + if (this->_i_cv_sw) { (void)fprintf(stdout, "\nthin line ... end.\n"); (void)fflush(stdout); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("thi : total %d loop, and %ld pixel deleted", ii, i32_pixel_count_total); pri_funct_msg_ttvr( @@ -5237,7 +5209,7 @@ int thinnest_ui16_image::exec05_thin(void) { void thinnest_ui16_image::mem_free(void) { #if 0 if (NULL != this->_ui16p_channel[0]) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr( "thinnest_ui16_image::mem_free()" ); } @@ -5247,7 +5219,7 @@ void thinnest_ui16_image::mem_free(void) { } #endif if (NULL != this->memory_free_this_) { - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::mem_free() <%x>", this->memory_free_this_); } @@ -5265,10 +5237,10 @@ int thinnest_ui16_image::mem_alloc(void) { this->mem_free(); /* 処理ごとのメッセージ */ - if (ON == this->_i_mv_sw) { + if (this->_i_mv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::mem_alloc()"); } - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr( "alloc ui16_image memory (%d+%d) x (%d+%d) x %d x %d bytes", this->_i32_xs * this->_i32_xd, 2, this->_i32_ys * this->_i32_yd, 2, 2, @@ -5279,7 +5251,7 @@ int thinnest_ui16_image::mem_alloc(void) { (uint16_t *)calloc((this->_i32_xs * this->_i32_xd + 2) * (this->_i32_ys * this->_i32_yd + 2) * 2, sizeof(uint16_t)); - if (ON == this->_i_pv_sw) { + if (this->_i_pv_sw) { pri_funct_msg_ttvr("thinnest_ui16_image::mem_alloc() memory <%x>", this->memory_free_this_); } @@ -5304,11 +5276,11 @@ int32_t thinnest_ui16_image::_one_side_thinner(void) { int32_t yy, i32_delete_count; /* 処理ごとのメッセージ */ - /******if (ON == this->_i_mv_sw) { + /******if (this->_i_mv_sw) { pri_funct_msg_ttvr( "thinnest_ui16_image::_one_side_thinner()" ); }******/ /* カウントダウン表示始め */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_start( this->_i32_ys ); } + // if (this->_i_cv_sw) { pri_funct_cv_start( this->_i32_ys ); } /* 始めのスキャンライン位置(画像から外れているものはNULLをいれる) */ ui16p_src_y1 = this->get_ui16p_src_channel() + this->_i32_xs; @@ -5320,7 +5292,7 @@ int32_t thinnest_ui16_image::_one_side_thinner(void) { i32_delete_count = 0; for (yy = 0; yy < this->_i32_ys; ++yy) { /* カウントダウン表示中 */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_run(yy); } + // if (this->_i_cv_sw) { pri_funct_cv_run(yy); } /* スキャンライン(とその前後のスキャンライン)毎の処理 */ i32_delete_count += this->_one_side_thinner_scanline( @@ -5337,7 +5309,7 @@ int32_t thinnest_ui16_image::_one_side_thinner(void) { } /* カウントダウン表示終了 */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_end(); } + // if (this->_i_cv_sw) { pri_funct_cv_end(); } /* 処理終了したらsrc,tgt画像交換 */ this->_swap_channel(); @@ -5436,7 +5408,7 @@ int32_t thinnest_ui16_image::_one_side_thinner_pixel( uint16_t *ui16p_tgt) { int32_t i32_delete_count; long l_off_count, l_white_count; - int i_sw, i_sw2; + bool i_sw, i_sw2; /* ui16p_src_x2bがNULLであってはならない */ assert(NULL != ui16p_src_x2b); @@ -5445,63 +5417,63 @@ int32_t thinnest_ui16_image::_one_side_thinner_pixel( i32_delete_count = 0; l_off_count = 0L; l_white_count = 0L; - i_sw = i_sw2 = OFF; + i_sw = i_sw2 = false; /* 時計回り(右回り)に見ていく */ /* 始め */ if (NULL != (ui16p_src_x1a)) { - i_sw = (0 < (*ui16p_src_x1a)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x1a); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } /* 次 ... */ if (NULL != (ui16p_src_x1b)) { - i_sw = (0 < (*ui16p_src_x1b)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x1b); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x1c)) { - i_sw = (0 < (*ui16p_src_x1c)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x1c); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x2c)) { - i_sw = (0 < (*ui16p_src_x2c)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x2c); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x3c)) { - i_sw = (0 < (*ui16p_src_x3c)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x3c); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x3b)) { - i_sw = (0 < (*ui16p_src_x3b)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x3b); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x3a)) { - i_sw = (0 < (*ui16p_src_x3a)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x3a); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } if (NULL != (ui16p_src_x2a)) { - i_sw = (0 < (*ui16p_src_x2a)) ? ON : OFF; - if (ON == i_sw) ++l_white_count; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x2a); + if (i_sw) ++l_white_count; + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } /* 調査の開始点のみがゼロのときのため(l_off_count)開始点を再度調査する */ if (NULL != (ui16p_src_x1a)) { - i_sw = (0 < (*ui16p_src_x1a)) ? ON : OFF; - if ((i_sw != i_sw2) && (OFF == i_sw)) ++l_off_count; + i_sw = 0 < (*ui16p_src_x1a); + if (!i_sw && i_sw2) ++l_off_count; i_sw2 = i_sw; } @@ -5533,18 +5505,18 @@ void thinnest_ui16_image::_rot90_by_clockwork(void) { uint16_t *ui16p_src, *ui16p_tgt_y, *ui16p_tgt_x; /* 処理ごとのメッセージ */ - /******if (ON == this->_i_mv_sw) { + /******if (this->_i_mv_sw) { pri_funct_msg_ttvr( "thinnest_ui16_image::_rot90_by_clockwork()" ); }******/ /* カウントダウン表示始め */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_start( this->_i32_ys ); } + // if (this->_i_cv_sw) { pri_funct_cv_start( this->_i32_ys ); } ui16p_src = this->get_ui16p_src_channel(); ui16p_tgt_y = this->get_ui16p_tgt_channel() + (this->_i32_ys - 1); for (yy = 0L; yy < this->_i32_ys; ++yy) { /* カウントダウン表示中 */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_run(yy); } + // if (this->_i_cv_sw) { pri_funct_cv_run(yy); } ui16p_tgt_x = ui16p_tgt_y; for (xx = 0L; xx < this->_i32_xs; ++xx) { @@ -5555,7 +5527,7 @@ void thinnest_ui16_image::_rot90_by_clockwork(void) { --ui16p_tgt_y; } /* カウントダウン表示終了 */ - // if (ON == this->_i_cv_sw) { pri_funct_cv_end(); } + // if (this->_i_cv_sw) { pri_funct_cv_end(); } /* 横と縦のサイズを交換 */ i32_tmp = this->_i32_xs; @@ -5720,7 +5692,8 @@ int igs_line_blur_brush_curve_blur_subpixel_( } int igs_line_blur_brush_curve_blur_all_( - int mv_sw, int pv_sw, int cv_sw, brush_curve_blur &cl_brush_curve_blur, + bool mv_sw, bool pv_sw, bool cv_sw, + brush_curve_blur &cl_brush_curve_blur, pixel_select_curve_blur_root &cl_pixel_select_curve_blur_root, pixel_line_root &cl_pixel_line_root @@ -5734,10 +5707,10 @@ int igs_line_blur_brush_curve_blur_all_( const int channels, const int bits, void *out // no_margin ) { /* 処理ごとのメッセージ */ - if (ON == mv_sw) { + if (mv_sw) { std::cout << "igs::line_blur::_brush_curve_blur_all()" << std::endl; } - if (ON == pv_sw) { + if (pv_sw) { std::cout << " curve blur points count is " << std::endl << cl_brush_curve_blur.get_i32_count() << std::endl << " power is " << std::endl @@ -5760,13 +5733,13 @@ int igs_line_blur_brush_curve_blur_all_( /* 画像をinからoutへコピーしておく */ (void)memcpy(out, in, height * width * channels * ((16 == bits) ? 2 : 1)); /* カウントダウン表示始め */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_start(height); } for (int yy = 0; yy < height; ++yy) { /* カウントダウン表示中 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_run(yy); } @@ -5787,7 +5760,7 @@ int igs_line_blur_brush_curve_blur_all_( } /* カウントダウン表示終了 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_end(); } @@ -6039,7 +6012,7 @@ void igs_line_blur_brush_smudge_line_( #include "igs_line_blur.h" // "pri.h" void igs_line_blur_brush_smudge_all_( - int mv_sw, int pv_sw, int cv_sw, + bool mv_sw, bool pv_sw, bool cv_sw, brush_smudge_circle &cl_brush_smudge_circle, pixel_line_root &cl_pixel_line_root, const void *in // no_margin , @@ -6050,11 +6023,11 @@ void igs_line_blur_brush_smudge_all_( const int channels, const int bits, void *out // no_margin ) { /* 処理ごとのメッセージ */ - if (ON == mv_sw) { + if (mv_sw) { std::cout << "igs::line_expand::_brush_smudge_all()" << std::endl; } - if (ON == pv_sw) { + if (pv_sw) { std::cout << " smudge ratio " << cl_brush_smudge_circle.get_d_ratio() << std::endl << " smudge brush size by pixel " @@ -6073,7 +6046,7 @@ void igs_line_blur_brush_smudge_all_( (void)memcpy(out, in, height * width * channels * ((16 == bits) ? 2 : 1)); /* カウントダウン表示始め */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_start(cl_pixel_line_root.get_i32_count()); } @@ -6088,7 +6061,7 @@ void igs_line_blur_brush_smudge_all_( } /* カウントダウン表示中 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_run(ii); } @@ -6096,7 +6069,7 @@ void igs_line_blur_brush_smudge_all_( channels, bits, out, clp_line); } /* カウントダウン表示終了 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_end(); } } @@ -6106,7 +6079,7 @@ void igs_line_blur_brush_smudge_all_( #include "igs_line_blur.h" // "pri.h" -void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, +void igs_line_blur_image_get_(const bool mv_sw, const bool cv_sw, const long reference_channel, thinnest_ui16_image &cl_thinnest_ui16_image @@ -6119,7 +6092,7 @@ void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, , const int channels, const int bits) { /* 処理ごとのメッセージ */ - if (ON == mv_sw) { + if (mv_sw) { std::cout << "igs_line_blur_image_get_()" << std::endl << "com : reference channel " << reference_channel << std::endl; } @@ -6129,7 +6102,7 @@ void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, unsigned short *out_incr = cl_thinnest_ui16_image.get_ui16p_src_channel(); /* カウントダウン表示始め */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_start(i32_ys); } @@ -6138,7 +6111,7 @@ void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, in_incr += reference_channel; for (int yy = 0; yy < i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_run(yy); } @@ -6157,7 +6130,7 @@ void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, for (int yy = 0; yy < i32_ys; ++yy) { /* カウントダウン表示中 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_run(yy); } @@ -6173,7 +6146,7 @@ void igs_line_blur_image_get_(const int mv_sw, const int cv_sw, } /* カウントダウン表示終了 */ - if (ON == cv_sw) { + if (cv_sw) { pri_funct_cv_end(); } } @@ -6223,15 +6196,15 @@ void igs::line_blur::convert( const int v_near_len /* min=2 def=160 incr=1 max=1000 */ , - const int mv_sw /* OFF */ + const bool mv_sw /* false=OFF */ , - const int pv_sw /* OFF */ + const bool pv_sw /* false=OFF */ , - const int cv_sw /* OFF */ + const bool cv_sw /* false=OFF */ , const long reference_channel /* 3 =Alpha:RGBA orBGRA */ , - const int debug_save_sw /* OFF */ + const bool debug_save_sw /* false=OFF */ , const int brush_action /* 0 =Curve Blur ,1=Smudge Brush */ ) { @@ -6264,7 +6237,7 @@ void igs::line_blur::convert( cl_brush_curve_blur.set_i_cv_sw(cv_sw); /* --- 処理ごとのメッセージ --- */ - if (ON == mv_sw) { + if (mv_sw) { std::cout << "igs::line_blur::convert()" << std::endl; } @@ -6279,7 +6252,7 @@ void igs::line_blur::convert( this->set_e_brush_smudge_action(); } else { this->set_e_brush_curve_blur_action(); - cl_pixel_line_root.set_i_same_way_exec_sw(OFF); + cl_pixel_line_root.set_i_same_way_exec_sw(false); }******/ /* 1: $b_blur_count :Wheel(min=1, default=51, increment=1, max=100) */ @@ -6363,7 +6336,7 @@ void igs::line_blur::convert( throw std::domain_error( "Error : cl_pixel_line_root.exec01020304() returns NG"); } - if (ON == debug_save_sw) { + if (debug_save_sw) { if (OK != cl_pixel_line_root.save_lines("tmp08_jaggy_lines.txt")) { throw std::domain_error( "Error : cl_pixel_line_root.save_lines(-) returns NG"); @@ -6387,7 +6360,7 @@ void igs::line_blur::convert( /* 中点をセットする */ cl_pixel_line_root.exec05_set_middle(); - if (ON == debug_save_sw) { + if (debug_save_sw) { if (OK != cl_pixel_line_root.save_middle_point("tmp12_middle_point.txt")) { throw std::domain_error( "Error : cl_pixel_line_root.save_middle_point(-) returns NG"); @@ -6407,7 +6380,7 @@ void igs::line_blur::convert( } /* 伸ばした線分の方向をそろえる */ - if (ON == debug_save_sw) { + if (debug_save_sw) { if (OK != cl_pixel_line_root.save_expand_vector("tmp13_expand_vector.txt")) { throw std::domain_error( @@ -6415,7 +6388,7 @@ void igs::line_blur::convert( } } cl_pixel_line_root.exec09_same_way_expand(&(cl_pixel_select_same_way_root)); - if (ON == debug_save_sw) { + if (debug_save_sw) { if (OK != cl_pixel_line_root.save_expand_vector("tmp14_same_way_vector.txt")) { throw std::domain_error( @@ -6426,7 +6399,7 @@ void igs::line_blur::convert( /* 伸ばした線分を再度スムースに */ cl_pixel_line_root.exec10_smooth_expand(); - if (ON == debug_save_sw) { + if (debug_save_sw) { if (OK != cl_pixel_line_root.save_expand_lines("tmp15_expand_lines.txt")) { throw std::domain_error( "Error : cl_pixel_line_root.save_expand_lines(-) returns NG"); @@ -6643,15 +6616,15 @@ void fx_(const TRasterP in_ras // with margin vector_smooth_retry, vector_near_ref, vector_near_len , - 0 /* int mv_sw 0=OFF */ + false /* bool mv_sw false=OFF */ , - 0 /* int pv_sw 0=OFF */ + false /* bool pv_sw false=OFF */ , - 0 /* int cv_sw 0=OFF */ + false /* bool cv_sw false=OFF */ , 3 /* long reference_channel 3=Red:RGBA or Blue:BGRA */ , - 0 /* int debug_save_sw 0=OFF */ + false /* bool debug_save_sw false=OFF */ , action_mode); ino::arr_to_ras(out_buffer->getRawData(), ino::channels(), out_ras, 0); diff --git a/toonz/sources/stdfx/iwa_particles.cpp b/toonz/sources/stdfx/iwa_particles.cpp index d7b28b2..9f8910b 100644 --- a/toonz/sources/stdfx/iwa_particles.cpp +++ b/toonz/sources/stdfx/iwa_particles.cpp @@ -232,9 +232,9 @@ void Iwa_Particle::create_Swing(const particles_values &values, random.getFloat() * (ranges.rotsca_range))); smperioda = changesigna; } - signx = random.getInt(0, 1) > 0 ? 1 : -1; - signy = random.getInt(0, 1) > 0 ? 1 : -1; - signa = random.getInt(0, 1) > 0 ? 1 : -1; + signx = random.getBool() ? 1 : -1; + signy = random.getBool() ? 1 : -1; + signa = random.getBool() ? 1 : -1; } /*-----------------------------------------------------------------*/ diff --git a/toonz/sources/stdfx/iwa_spectrumfx.h b/toonz/sources/stdfx/iwa_spectrumfx.h index ff29c49..6be4562 100644 --- a/toonz/sources/stdfx/iwa_spectrumfx.h +++ b/toonz/sources/stdfx/iwa_spectrumfx.h @@ -8,7 +8,6 @@ #ifndef IWA_SPECTRUM_H #define IWA_SPECTRUM_H -#include "tfxparam.h" #include "stdfx.h" #include "tfxparam.h" diff --git a/toonz/sources/stdfx/iwa_textfx.cpp b/toonz/sources/stdfx/iwa_textfx.cpp new file mode 100644 index 0000000..41892f0 --- /dev/null +++ b/toonz/sources/stdfx/iwa_textfx.cpp @@ -0,0 +1,250 @@ +#include "iwa_textfx.h" + +#include "tparamuiconcept.h" +#include +#include +#include + +//------------------------------------------------------------------ + +Iwa_TextFx::Iwa_TextFx() + : m_text(L"Lorem ipsum") + , m_hAlign(new TIntEnumParam(Qt::AlignLeft, "Left")) + , m_center(TPointD(0.0, 0.0)) + , m_width(200.0) + , m_height(60.0) + , m_font(new TFontParam()) + , m_textColor(TPixel32::Black) + , m_boxColor(TPixel32::Transparent) + , m_showBorder(false) { + m_targetType->setValue(INPUT_TEXT); + + m_hAlign->addItem(Qt::AlignRight, "Right"); + m_hAlign->addItem(Qt::AlignHCenter, "Center"); + m_hAlign->addItem(Qt::AlignJustify, "Justify"); + + m_text->setMultiLineEnabled(true); + + m_center->getX()->setMeasureName("fxLength"); + m_center->getY()->setMeasureName("fxLength"); + m_width->setMeasureName("fxLength"); + m_height->setMeasureName("fxLength"); + + m_width->setValueRange(1.0, (std::numeric_limits::max)()); + m_height->setValueRange(1.0, (std::numeric_limits::max)()); + + // set the initial font size to 30 + QFont font; + font.fromString(QString::fromStdWString(m_font->getValue())); + font.setPixelSize(30); + m_font->setValue(font.toString().toStdWString(), true); + + bindParam(this, "targetType", m_targetType); + bindParam(this, "columnIndex", m_columnIndex); + bindParam(this, "text", m_text); + bindParam(this, "hAlign", m_hAlign); + bindParam(this, "center", m_center); + bindParam(this, "width", m_width); + bindParam(this, "height", m_height); + bindParam(this, "font", m_font); + bindParam(this, "textColor", m_textColor); + bindParam(this, "boxColor", m_boxColor); + bindParam(this, "showBorder", m_showBorder); +} + +//------------------------------------------------------------------ + +bool Iwa_TextFx::doGetBBox(double frame, TRectD &bBox, + const TRenderSettings &ri) { + bBox = TConsts::infiniteRectD; + return true; +} + +//------------------------------------------------------------------ + +void Iwa_TextFx::doCompute(TTile &tile, double frame, + const TRenderSettings &ri) { + QString text; + if (m_targetType->getValue() == INPUT_TEXT) + text = QString::fromStdWString(m_text->getValue()); + else + text = m_noteLevelStr; + if (text.isEmpty()) return; + + QFont font; + font.fromString(QString::fromStdWString(m_font->getValue())); + + double fac = sqrt(fabs(ri.m_affine.det())); + int size = (int)(fac * fabs(font.pixelSize())); + + TPoint center = convert( + fac * m_center->getValue(frame) - + (tile.m_pos + tile.getRaster()->getCenterD()) + + TPointD(ri.m_cameraBox.getLx() / 2.0, ri.m_cameraBox.getLy() / 2.0)); + + QRect textBoxRect(0, 0, fac * m_width->getValue(frame), + fac * m_height->getValue(frame)); + textBoxRect.moveCenter(QPoint(center.x, center.y)); + + Qt::AlignmentFlag hAlignFlag = (Qt::AlignmentFlag)m_hAlign->getValue(); + + // For simplification, text will always be "wrapped". + // If user would like to make the line with no break, they can just expand the + // boundary or set the smaller font size. + int flag = hAlignFlag | Qt::AlignVCenter | Qt::TextWordWrap; + + QFont tmpFont(font); + tmpFont.setPixelSize(100); + QFontMetricsF tmpFm(tmpFont); + QRectF bbox = tmpFm.boundingRect(textBoxRect, flag, text); + + float ratio = std::min(textBoxRect.width() / bbox.width(), + textBoxRect.height() / bbox.height()); + + // compute the font size which will just fit the item region + int fontSize = (int)(100.0f * ratio); + tmpFont.setPixelSize(fontSize); + tmpFm = QFontMetricsF(tmpFont); + bbox = tmpFm.boundingRect(textBoxRect, flag, text); + bool isInRect; + if (textBoxRect.width() >= bbox.width() && + textBoxRect.height() >= bbox.height()) + isInRect = true; + else + isInRect = false; + while (1) { + fontSize += (isInRect) ? 1 : -1; + if (fontSize <= 0) // cannot draw + return; + if (isInRect && fontSize >= size) break; + tmpFont.setPixelSize(fontSize); + tmpFm = QFontMetricsF(tmpFont); + bbox = tmpFm.boundingRect(textBoxRect, flag, text); + + bool newIsInRect = (textBoxRect.width() >= bbox.width() && + textBoxRect.height() >= bbox.height()); + if (isInRect != newIsInRect) { + if (isInRect) fontSize--; + break; + } + } + + if (size < fontSize) { + fontSize = size; + } + + font.setPixelSize(fontSize); + tmpFm = QFontMetricsF(font); + bbox = tmpFm.boundingRect(textBoxRect, flag, text); + + double lineWidth = 0.1 * (double)fontSize; + + // Usually the text bounding box has less horizontal margin than vertical. + // So here I added more margin to width. + QImage img(bbox.width() + (int)(lineWidth * 4), + bbox.height() + (int)(lineWidth * 2), + QImage::Format_ARGB32_Premultiplied); + img.fill(Qt::transparent); + + bbox.moveCenter(img.rect().center()); + + QPainter painter(&img); + TPixel32 boxColor = m_boxColor->getValue(frame); + TPixel32 color = m_textColor->getValue(frame); + + if (boxColor.m > 0) + painter.fillRect(img.rect(), QColor((int)boxColor.r, (int)boxColor.g, + (int)boxColor.b, (int)boxColor.m)); + + QPen pen(QColor((int)color.r, (int)color.g, (int)color.b, (int)color.m)); + painter.setPen(pen); + painter.setFont(font); + painter.drawText(bbox, flag, text); + + if (m_showBorder->getValue()) { + pen.setWidthF(lineWidth); + pen.setJoinStyle(Qt::MiterJoin); + painter.setPen(pen); + painter.drawRect(img.rect().adjusted(lineWidth / 2, lineWidth / 2, + -lineWidth / 2, -lineWidth / 2)); + } + + TPoint imgRootPos = center - TPoint(img.width() / 2, img.height() / 2); + + tile.getRaster()->clear(); + TRaster32P ras32 = (TRaster32P)tile.getRaster(); + TRaster64P ras64 = (TRaster64P)tile.getRaster(); + if (ras32) + putTextImage(ras32, imgRootPos, img); + else if (ras64) + putTextImage(ras64, imgRootPos, img); + else + throw TException("Iwa_TextFx: unsupported Pixel Type"); +} + +//------------------------------------------------------------------ + +void Iwa_TextFx::getParamUIs(TParamUIConcept *&concepts, int &length) { + concepts = new TParamUIConcept[length = 2]; + + concepts[0].m_type = TParamUIConcept::POINT; + concepts[0].m_label = "Center"; + concepts[0].m_params.push_back(m_center); + + concepts[1].m_type = TParamUIConcept::RECT; + concepts[1].m_params.push_back(m_width); + concepts[1].m_params.push_back(m_height); + concepts[1].m_params.push_back(m_center); +} + +//------------------------------------------------------------------ + +std::string Iwa_TextFx::getAlias(double frame, + const TRenderSettings &info) const { + std::string alias = getFxType(); + alias += "["; + + std::string paramalias(""); + for (int i = 0; i < getParams()->getParamCount(); ++i) { + TParam *param = getParams()->getParam(i); + paramalias += param->getName() + "=" + param->getValueAlias(frame, 3); + } + + if (m_targetType->getValue() == INPUT_TEXT) + return alias + "," + std::to_string(getIdentifier()) + paramalias + "]"; + else + return alias + std::to_string(frame) + "," + + std::to_string(getIdentifier()) + paramalias + "]"; +} + +//------------------------------------------------------------------ + +template +void Iwa_TextFx::putTextImage(const RASTER srcRas, TPoint &pos, QImage &img) { + for (int j = 0; j < img.height(); j++) { + int rasY = pos.y + j; + if (rasY < 0) continue; + if (srcRas->getLy() <= rasY) break; + + PIXEL *pix = srcRas->pixels(rasY); + QRgb *img_p = (QRgb *)img.scanLine(img.height() - j - 1); + for (int i = 0; i < img.width(); i++, img_p++) { + int rasX = pos.x + i; + if (rasX < 0) continue; + if (srcRas->getLx() <= rasX) break; + + pix[rasX].r = (typename PIXEL::Channel)( + qRed(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX); + pix[rasX].g = (typename PIXEL::Channel)( + qGreen(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX); + pix[rasX].b = (typename PIXEL::Channel)( + qBlue(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX); + pix[rasX].m = (typename PIXEL::Channel)( + qAlpha(*img_p) * (int)PIXEL::maxChannelValue / (int)UCHAR_MAX); + } + } +} + +//============================================================================== + +FX_PLUGIN_IDENTIFIER(Iwa_TextFx, "iwa_TextFx"); \ No newline at end of file diff --git a/toonz/sources/stdfx/iwa_textfx.h b/toonz/sources/stdfx/iwa_textfx.h new file mode 100644 index 0000000..24ea20e --- /dev/null +++ b/toonz/sources/stdfx/iwa_textfx.h @@ -0,0 +1,47 @@ +#pragma once + +#ifndef IWA_TEXTFX_H +#define IWA_TEXTFX_H + +#include "tparamset.h" +#include "textawarebasefx.h" + +//****************************************************************** +// Iwa_Text Fx class +//****************************************************************** + +class Iwa_TextFx final : public TextAwareBaseFx { + FX_PLUGIN_DECLARATION(Iwa_TextFx) +protected: + TStringParamP m_text; + + TIntEnumParamP m_hAlign; + + TPointParamP m_center; + TDoubleParamP m_width; + TDoubleParamP m_height; + + TFontParamP m_font; + TPixelParamP m_textColor; + TPixelParamP m_boxColor; + TBoolParamP m_showBorder; + + template + void putTextImage(const RASTER srcRas, TPoint &pos, QImage &img); + +public: + Iwa_TextFx(); + + bool canHandle(const TRenderSettings &info, double frame) override { + return true; + } + + bool doGetBBox(double frame, TRectD &bBox, + const TRenderSettings &ri) override; + void doCompute(TTile &tile, double frame, const TRenderSettings &ri) override; + void getParamUIs(TParamUIConcept *&concepts, int &length) override; + + std::string getAlias(double frame, + const TRenderSettings &info) const override; +}; +#endif \ No newline at end of file diff --git a/toonz/sources/stdfx/motionblurfx.cpp b/toonz/sources/stdfx/motionblurfx.cpp index 2d564a0..9d2de20 100644 --- a/toonz/sources/stdfx/motionblurfx.cpp +++ b/toonz/sources/stdfx/motionblurfx.cpp @@ -446,10 +446,26 @@ public: std::string getAlias(double frame, const TRenderSettings &info) const override { + std::string alias = getFxType(); + alias += "["; + + // alias of the effects related to the input ports separated by commas + // a port that is not connected to an alias blank (empty string) + int i; + for (i = 0; i < getInputPortCount(); i++) { + TFxPort *port = getInputPort(i); + if (port->isConnected()) { + TRasterFxP ifx = port->getFx(); + assert(ifx); + alias += ifx->getAlias(frame, info); + } + alias += ","; + } + unsigned long id = getIdentifier(); double value = m_intensity->getValue(frame); - return getFxType() + "[" + std::to_string(id) + "," + - std::to_string(frame) + "," + std::to_string(value) + "]"; + return alias + std::to_string(id) + "," + std::to_string(frame) + "," + + std::to_string(value) + "]"; } }; diff --git a/toonz/sources/stdfx/particles.cpp b/toonz/sources/stdfx/particles.cpp index 2bb9666..b2e4e6a 100644 --- a/toonz/sources/stdfx/particles.cpp +++ b/toonz/sources/stdfx/particles.cpp @@ -249,9 +249,9 @@ void Particle::create_Swing(const particles_values &values, random.getFloat() * (ranges.rotsca_range))); smperioda = changesigna; } - signx = random.getInt(0, 1) > 0 ? 1 : -1; - signy = random.getInt(0, 1) > 0 ? 1 : -1; - signa = random.getInt(0, 1) > 0 ? 1 : -1; + signx = random.getBool() ? 1 : -1; + signy = random.getBool() ? 1 : -1; + signa = random.getBool() ? 1 : -1; } /*-----------------------------------------------------------------*/ diff --git a/toonz/sources/stdfx/shaderfx.cpp b/toonz/sources/stdfx/shaderfx.cpp index 2b20347..bccff39 100644 --- a/toonz/sources/stdfx/shaderfx.cpp +++ b/toonz/sources/stdfx/shaderfx.cpp @@ -31,7 +31,6 @@ // tcg includes #include "tcg/tcg_function_types.h" -#include "tcg/tcg_unique_ptr.h" // Boost includes #include @@ -1008,7 +1007,7 @@ void ShaderFx::doCompute(TTile &tile, double frame, // Calculate input tiles ::ContextLocker cLocker(context); - tcg::unique_ptr inTiles( + std::unique_ptr inTiles( new TTile[pCount]); // NOTE: Input tiles must be STORED - they cannot // be passed immediately to OpenGL, since *other shader if (pCount > 0) // fxs*, with the very same host context, could lie diff --git a/toonz/sources/stdfx/textawarebasefx.h b/toonz/sources/stdfx/textawarebasefx.h new file mode 100644 index 0000000..a25b0da --- /dev/null +++ b/toonz/sources/stdfx/textawarebasefx.h @@ -0,0 +1,32 @@ +#pragma once +#ifndef TEXTAWAREBASEFX_H +#define TEXTAWAREBASEFX_H + +#include "tfxparam.h" +#include "stdfx.h" + +class TextAwareBaseFx : public TStandardZeraryFx { +protected: + QString m_noteLevelStr; + + TIntEnumParamP m_targetType; + TIntParamP m_columnIndex; + +public: + enum SourceType { NEARBY_COLUMN, SPECIFIED_COLUMN, INPUT_TEXT }; + + TextAwareBaseFx() + : m_targetType(new TIntEnumParam(NEARBY_COLUMN, "Nearby Note Column")) + , m_columnIndex(0) { + m_targetType->addItem(SPECIFIED_COLUMN, "Specified Note Column"); + m_targetType->addItem(INPUT_TEXT, "Input Text"); + } + + bool isZerary() const override { return true; } + + void setNoteLevelStr(QString str) { m_noteLevelStr = str; } + SourceType getSourceType() { return (SourceType)(m_targetType->getValue()); } + int getNoteColumnIndex() { return m_columnIndex->getValue() - 1; } +}; + +#endif diff --git a/toonz/sources/tcleanupper/tcleanupper.cpp b/toonz/sources/tcleanupper/tcleanupper.cpp index a8f41fa..852163e 100644 --- a/toonz/sources/tcleanupper/tcleanupper.cpp +++ b/toonz/sources/tcleanupper/tcleanupper.cpp @@ -62,11 +62,8 @@ inline ostream &operator<<(ostream &out, const TFilePath &fp) { //------------------------------------------------------------------------ namespace { -const char *applicationName = "OpenToonz"; -const char *applicationVersion = "1.2"; -const char *applicationFullName = "OpenToonz 1.2"; -const char *rootVarName = "TOONZROOT"; -const char *systemVarPrefix = "TOONZ"; +const char *rootVarName = "TOONZROOT"; +const char *systemVarPrefix = "TOONZ"; namespace { @@ -492,8 +489,6 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); // questo definisce la registry root e inizializza TEnv - TEnv::setApplication(applicationName, applicationVersion); - TEnv::setApplicationFullName(applicationFullName); TEnv::setRootVarName(rootVarName); TEnv::setSystemVarPrefix(systemVarPrefix); TSystem::hasMainLoop(false); diff --git a/toonz/sources/tcomposer/tcomposer.cpp b/toonz/sources/tcomposer/tcomposer.cpp index be64744..f7fc944 100644 --- a/toonz/sources/tcomposer/tcomposer.cpp +++ b/toonz/sources/tcomposer/tcomposer.cpp @@ -103,11 +103,8 @@ namespace { // (es PROJECTS etc.) // -const char *applicationName = "OpenToonz"; -const char *applicationVersion = "1.2"; -const char *applicationFullName = "OpenToonz 1.2"; -const char *rootVarName = "TOONZROOT"; -const char *systemVarPrefix = "TOONZ"; +const char *rootVarName = "TOONZROOT"; +const char *systemVarPrefix = "TOONZ"; // TODO: forse anche questo andrebbe in tnzbase // ci possono essere altri programmi offline oltre al tcomposer @@ -603,8 +600,6 @@ int main(int argc, char *argv[]) { TThread::init(); // questo definisce la registry root e inizializza TEnv - TEnv::setApplication(applicationName, applicationVersion); - TEnv::setApplicationFullName(applicationFullName); TEnv::setRootVarName(rootVarName); TEnv::setSystemVarPrefix(systemVarPrefix); TSystem::hasMainLoop(true); diff --git a/toonz/sources/tconverter/tconverter.cpp b/toonz/sources/tconverter/tconverter.cpp index 8a71275..ede0a42 100644 --- a/toonz/sources/tconverter/tconverter.cpp +++ b/toonz/sources/tconverter/tconverter.cpp @@ -37,10 +37,8 @@ typedef QualifierT FilePathQualifier; #define RENDER_LICENSE_NOT_FOUND 888 -const char *applicationVersion = "1.2"; -const char *applicationName = "OpenToonz"; -const char *rootVarName = "TOONZROOT"; -const char *systemVarPrefix = "TOONZ"; +const char *rootVarName = "TOONZROOT"; +const char *systemVarPrefix = "TOONZ"; namespace { @@ -357,7 +355,6 @@ void convert(const TFilePath &source, const TFilePath &dest, //------------------------------------------------------------------------ int main(int argc, char *argv[]) { - TEnv::setApplication(applicationName, applicationVersion); TEnv::setRootVarName(rootVarName); TEnv::setSystemVarPrefix(systemVarPrefix); TFilePath fp = TEnv::getStuffDir(); diff --git a/toonz/sources/tnzbase/tscanner/tscannerepson.cpp b/toonz/sources/tnzbase/tscanner/tscannerepson.cpp index f3ac822..df3e5de 100644 --- a/toonz/sources/tnzbase/tscanner/tscannerepson.cpp +++ b/toonz/sources/tnzbase/tscanner/tscannerepson.cpp @@ -242,7 +242,7 @@ throw TException("Scan area too large, select a correct paper size"); TRectD scanArea = params.isPreview() ? params.getScanArea() : params.getCropBox(); scanArea2pix(params, offsetx, offsety, dimlx, dimly, scanArea); - tswap(dimlx, dimly); + std::swap(dimlx, dimly); unsigned int bytes; diff --git a/toonz/sources/tnzcore/CMakeLists.txt b/toonz/sources/tnzcore/CMakeLists.txt index 16603f9..658c70e 100644 --- a/toonz/sources/tnzcore/CMakeLists.txt +++ b/toonz/sources/tnzcore/CMakeLists.txt @@ -112,6 +112,7 @@ set(HEADERS ${MOC_HEADERS} ../include/tiio_bmp.h ../include/tiio_jpg.h ../include/tiio_jpg_util.h + ../include/tiio_jpg_exif.h ../include/tiio_std.h ../include/ttoonzimage.h ../include/tipc.h @@ -226,6 +227,7 @@ set(SOURCES ../common/tiio/tiio_bmp.cpp ../common/tiio/tiio_jpg.cpp ../common/tiio/tiio_jpg_util.cpp + ../common/tiio/tiio_jpg_exif.cpp ../common/tiio/tiio_std.cpp ../common/tiio/movsettings.cpp ../common/tiio/compatibility/tfile_io.c diff --git a/toonz/sources/tnzext/StrokeDeformation.cpp b/toonz/sources/tnzext/StrokeDeformation.cpp index e88bb11..fad64cb 100644 --- a/toonz/sources/tnzext/StrokeDeformation.cpp +++ b/toonz/sources/tnzext/StrokeDeformation.cpp @@ -18,7 +18,6 @@ #include "ext/StraightCornerDeformation.h" #include "ext/CornerDeformation.h" -#include "ext/SmoothDeformation.h" #include "ext/StrokeDeformationImpl.h" #include "DeformationSelector.h" diff --git a/toonz/sources/tnztools/CMakeLists.txt b/toonz/sources/tnztools/CMakeLists.txt index 06626e1..51942b1 100644 --- a/toonz/sources/tnztools/CMakeLists.txt +++ b/toonz/sources/tnztools/CMakeLists.txt @@ -14,12 +14,12 @@ set(MOC_HEADERS rulertool.h stylepickertool.h viewtools.h + toonzrasterbrushtool.h ) set(HEADERS ${MOC_HEADERS} autofill.h bluredbrush.h - brushtool.h ../include/tools/cursormanager.h ../include/tools/cursors.h ../include/tools/levelselection.h @@ -36,6 +36,8 @@ set(HEADERS ${MOC_HEADERS} ../include/tools/toolutils.h ../include/tools/RGBpicker.h mypainttoonzbrush.h + shifttracetool.h + toonzvectorbrushtool.h ) set(SOURCES @@ -48,7 +50,6 @@ set(SOURCES toolutils.cpp bendertool.cpp bluredbrush.cpp - brushtool.cpp controlpointeditortool.cpp cuttertool.cpp edittool.cpp @@ -96,6 +97,9 @@ set(SOURCES fingertool.cpp rulertool.cpp mypainttoonzbrush.cpp + shifttracetool.cpp + toonzrasterbrushtool.cpp + toonzvectorbrushtool.cpp ) set(RESOURCES tnztools.qrc) diff --git a/toonz/sources/tnztools/autofilltlv.cpp b/toonz/sources/tnztools/autofilltlv.cpp index 509e173..a854c89 100644 --- a/toonz/sources/tnztools/autofilltlv.cpp +++ b/toonz/sources/tnztools/autofilltlv.cpp @@ -264,7 +264,7 @@ bool rect_autofill_apply(const TToonzImageP &imgToApply, int x1, int y1, int x2, /*..........................................................................*/ /* Matching basato sulla probabilita' di colore */ /*..........................................................................*/ - if (FALSE) { + if (false) { bool recomputeBBox = false; for (i = 0; i < F_work.n; i++) { if (F_work.array[i].match < 0) { @@ -453,7 +453,7 @@ bool autofill_apply(const TToonzImageP &imgToApply, bool selective, /*..........................................................................*/ /* Matching basato sulla probabilita' di colore */ /*..........................................................................*/ - if (FALSE) { + if (false) { bool recomputeBBox = false; for (i = 0; i < F_work.n; i++) { if (F_work.array[i].match < 0) { @@ -759,7 +759,7 @@ static void rinomina(int regione1, int regione2, int num_regioni, { struct vicine *appo, *old, appo1; int i; - int trovato = FALSE; + bool trovato = false; PRINTF("Rinomino %d %d Regioni: %d \n", regione1, regione2, num_regioni); /* mostra_vicini(rlst); */ @@ -791,7 +791,7 @@ static void rinomina(int regione1, int regione2, int num_regioni, appo->region_id = regione2; old = appo; appo = appo->next; - trovato = TRUE; + trovato = true; } } else /* region_id non e' region2 o regione 1 */ { diff --git a/toonz/sources/tnztools/brushtool.cpp b/toonz/sources/tnztools/brushtool.cpp deleted file mode 100644 index 6b51831..0000000 --- a/toonz/sources/tnztools/brushtool.cpp +++ /dev/null @@ -1,2897 +0,0 @@ - - -#include "brushtool.h" - -// TnzTools includes -#include "tools/toolhandle.h" -#include "tools/toolutils.h" -#include "tools/tooloptions.h" -#include "bluredbrush.h" - -// TnzQt includes -#include "toonzqt/dvdialog.h" -#include "toonzqt/imageutils.h" - -// TnzLib includes -#include "toonz/tobjecthandle.h" -#include "toonz/txsheethandle.h" -#include "toonz/txshlevelhandle.h" -#include "toonz/tframehandle.h" -#include "toonz/tcolumnhandle.h" -#include "toonz/txsheet.h" -#include "toonz/tstageobject.h" -#include "toonz/tstageobjectspline.h" -#include "toonz/rasterstrokegenerator.h" -#include "toonz/ttileset.h" -#include "toonz/txshsimplelevel.h" -#include "toonz/toonzimageutils.h" -#include "toonz/palettecontroller.h" -#include "toonz/stage2.h" -#include "toonz/preferences.h" - -// TnzCore includes -#include "tstream.h" -#include "tcolorstyles.h" -#include "tvectorimage.h" -#include "tenv.h" -#include "tregion.h" -#include "tinbetween.h" - -#include "tgl.h" -#include "trop.h" - -// Qt includes -#include - -using namespace ToolUtils; - -TEnv::DoubleVar VectorBrushMinSize("InknpaintVectorBrushMinSize", 1); -TEnv::DoubleVar VectorBrushMaxSize("InknpaintVectorBrushMaxSize", 5); -TEnv::IntVar VectorCapStyle("InknpaintVectorCapStyle", 1); -TEnv::IntVar VectorJoinStyle("InknpaintVectorJoinStyle", 1); -TEnv::IntVar VectorMiterValue("InknpaintVectorMiterValue", 4); -TEnv::DoubleVar RasterBrushMinSize("InknpaintRasterBrushMinSize", 1); -TEnv::DoubleVar RasterBrushMaxSize("InknpaintRasterBrushMaxSize", 5); -TEnv::DoubleVar BrushAccuracy("InknpaintBrushAccuracy", 20); -TEnv::DoubleVar BrushSmooth("InknpaintBrushSmooth", 0); -TEnv::IntVar BrushDrawOrder("InknpaintBrushDrawOrder", 0); -TEnv::IntVar BrushBreakSharpAngles("InknpaintBrushBreakSharpAngles", 0); -TEnv::IntVar RasterBrushPencilMode("InknpaintRasterBrushPencilMode", 0); -TEnv::IntVar BrushPressureSensitivity("InknpaintBrushPressureSensitivity", 1); -TEnv::DoubleVar RasterBrushHardness("RasterBrushHardness", 100); -TEnv::IntVar VectorBrushFrameRange("VectorBrushFrameRange", 0); -TEnv::IntVar VectorBrushSnap("VectorBrushSnap", 0); -TEnv::IntVar VectorBrushSnapSensitivity("VectorBrushSnapSensitivity", 0); - -//------------------------------------------------------------------- - -#define ROUNDC_WSTR L"round_cap" -#define BUTT_WSTR L"butt_cap" -#define PROJECTING_WSTR L"projecting_cap" -#define ROUNDJ_WSTR L"round_join" -#define BEVEL_WSTR L"bevel_join" -#define MITER_WSTR L"miter_join" -#define CUSTOM_WSTR L"" - -#define LINEAR_WSTR L"Linear" -#define EASEIN_WSTR L"In" -#define EASEOUT_WSTR L"Out" -#define EASEINOUT_WSTR L"In&Out" - -#define LOW_WSTR L"Low" -#define MEDIUM_WSTR L"Med" -#define HIGH_WSTR L"High" - -const double SNAPPING_LOW = 5.0; -const double SNAPPING_MEDIUM = 25.0; -const double SNAPPING_HIGH = 100.0; -//------------------------------------------------------------------- -// -// (Da mettere in libreria) : funzioni che spezzano una stroke -// nei suoi punti angolosi. Lo facciamo specialmente per limitare -// i problemi di fill. -// -//------------------------------------------------------------------- - -// -// Split a stroke in n+1 parts, according to n parameter values -// Input: -// stroke = stroke to split -// parameterValues[] = vector of parameters where I want to split the -// stroke -// assert: 0 ¶meterValues, - std::vector &strokes) { - TThickPoint p2; - std::vector points; - TThickPoint lastPoint = stroke->getControlPoint(0); - int n = parameterValues.size(); - int chunk; - double t; - int last_chunk = -1, startPoint = 0; - double lastLocT = 0; - - for (int i = 0; i < n; i++) { - points.push_back(lastPoint); // Add first point of the stroke - double w = - parameterValues[i]; // Global parameter. along the stroke 0<=w<=1 - stroke->getChunkAndT(w, chunk, - t); // t: local parameter in the chunk-th quadratic - - if (i == 0) - startPoint = 1; - else { - int indexAfterLastT = - stroke->getControlPointIndexAfterParameter(parameterValues[i - 1]); - startPoint = indexAfterLastT; - if ((indexAfterLastT & 1) && lastLocT != 1) startPoint++; - } - int endPoint = 2 * chunk + 1; - if (lastLocT != 1 && i > 0) { - if (last_chunk != chunk || t == 1) - points.push_back(p2); // If the last local t is not an extreme - // add the point p2 - } - - for (int j = startPoint; j < endPoint; j++) - points.push_back(stroke->getControlPoint(j)); - - TThickPoint p, A, B, C; - p = stroke->getPoint(w); - C = stroke->getControlPoint(2 * chunk + 2); - B = stroke->getControlPoint(2 * chunk + 1); - A = stroke->getControlPoint(2 * chunk); - p.thick = A.thick; - - if (last_chunk != chunk) { - TThickPoint p1 = (1 - t) * A + t * B; - points.push_back(p1); - p.thick = p1.thick; - } else { - if (t != 1) { - // If the i-th cut point belong to the same chunk of the (i-1)-th cut - // point. - double tInters = lastLocT / t; - TThickPoint p11 = (1 - t) * A + t * B; - TThickPoint p1 = (1 - tInters) * p11 + tInters * p; - points.push_back(p1); - p.thick = p1.thick; - } - } - - points.push_back(p); - - if (t != 1) p2 = (1 - t) * B + t * C; - - assert(points.size() & 1); - - // Add new stroke - TStroke *strokeAdd = new TStroke(points); - strokeAdd->setStyle(stroke->getStyle()); - strokeAdd->outlineOptions() = stroke->outlineOptions(); - strokes.push_back(strokeAdd); - - lastPoint = p; - last_chunk = chunk; - lastLocT = t; - points.clear(); - } - // Add end stroke - points.push_back(lastPoint); - - if (lastLocT != 1) points.push_back(p2); - - startPoint = - stroke->getControlPointIndexAfterParameter(parameterValues[n - 1]); - if ((stroke->getControlPointIndexAfterParameter(parameterValues[n - 1]) & - 1) && - lastLocT != 1) - startPoint++; - for (int j = startPoint; j < stroke->getControlPointCount(); j++) - points.push_back(stroke->getControlPoint(j)); - - assert(points.size() & 1); - TStroke *strokeAdd = new TStroke(points); - strokeAdd->setStyle(stroke->getStyle()); - strokeAdd->outlineOptions() = stroke->outlineOptions(); - strokes.push_back(strokeAdd); - points.clear(); -} - -// Compute Parametric Curve Curvature -// By Formula: -// k(t)=(|p'(t) x p''(t)|)/Norm2(p')^3 -// p(t) is parametric curve -// Input: -// dp = First Derivate. -// ddp = Second Derivate -// Output: -// return curvature value. -// Note: if the curve is a single point (that's dp=0) or it is a straight -// line (that's ddp=0) return 0 - -static double curvature(TPointD dp, TPointD ddp) { - if (dp == TPointD(0, 0)) - return 0; - else - return fabs(cross(dp, ddp) / pow(norm2(dp), 1.5)); -} - -// Find the max curvature points of a stroke. -// Input: -// stroke. -// angoloLim = Value (radians) of the Corner between two tangent vector. -// Up this value the two corner can be considered angular. -// curvMaxLim = Value of the max curvature. -// Up this value the point can be considered a max curvature -// point. -// Output: -// parameterValues = vector of max curvature parameter points - -static void findMaxCurvPoints(TStroke *stroke, const float &angoloLim, - const float &curvMaxLim, - std::vector ¶meterValues) { - TPointD tg1, tg2; // Tangent vectors - - TPointD dp, ddp; // First and Second derivate. - - parameterValues.clear(); - int cpn = stroke ? stroke->getControlPointCount() : 0; - for (int j = 2; j < cpn; j += 2) { - TPointD p0 = stroke->getControlPoint(j - 2); - TPointD p1 = stroke->getControlPoint(j - 1); - TPointD p2 = stroke->getControlPoint(j); - - TPointD q = p1 - (p0 + p2) * 0.5; - - // Search corner point - if (j > 2) { - tg2 = -p0 + p2 + 2 * q; // Tangent vector to this chunk at t=0 - double prod_scal = - tg2 * tg1; // Inner product between tangent vectors at t=0. - assert(tg1 != TPointD(0, 0) || tg2 != TPointD(0, 0)); - // Compute corner between two tangent vectors - double angolo = - acos(prod_scal / (pow(norm2(tg2), 0.5) * pow(norm2(tg1), 0.5))); - - // Add corner point - if (angolo > angoloLim) { - double w = getWfromChunkAndT(stroke, (UINT)(0.5 * (j - 2)), - 0); // transform lacal t to global t - parameterValues.push_back(w); - } - } - tg1 = -p0 + p2 - 2 * q; // Tangent vector to this chunk at t=1 - - // End search corner point - - // Search max curvature point - // Value of t where the curvature function has got an extreme. - // (Point where first derivate is null) - double estremo_int = 0; - double t = -1; - if (q != TPointD(0, 0)) { - t = 0.25 * (2 * q.x * q.x + 2 * q.y * q.y - q.x * p0.x + q.x * p2.x - - q.y * p0.y + q.y * p2.y) / - (q.x * q.x + q.y * q.y); - - dp = -p0 + p2 + 2 * q - 4 * t * q; // First derivate of the curve - ddp = -4 * q; // Second derivate of the curve - estremo_int = curvature(dp, ddp); - - double h = 0.01; - dp = -p0 + p2 + 2 * q - 4 * (t + h) * q; - double c_dx = curvature(dp, ddp); - dp = -p0 + p2 + 2 * q - 4 * (t - h) * q; - double c_sx = curvature(dp, ddp); - // Check the point is a max and not a minimum - if (estremo_int < c_dx && estremo_int < c_sx) { - estremo_int = 0; - } - } - double curv_max = estremo_int; - - // Compute curvature at the extreme of interval [0,1] - // Compute curvature at t=0 (Left extreme) - dp = -p0 + p2 + 2 * q; - double estremo_sx = curvature(dp, ddp); - - // Compute curvature at t=1 (Right extreme) - dp = -p0 + p2 - 2 * q; - double estremo_dx = curvature(dp, ddp); - - // Compare curvature at the extreme of interval [0,1] with the internal - // value - double t_ext; - if (estremo_sx >= estremo_dx) - t_ext = 0; - else - t_ext = 1; - double maxEstremi = std::max(estremo_dx, estremo_sx); - if (maxEstremi > estremo_int) { - t = t_ext; - curv_max = maxEstremi; - } - - // Add max curvature point - if (t >= 0 && t <= 1 && curv_max > curvMaxLim) { - double w = getWfromChunkAndT(stroke, (UINT)(0.5 * (j - 2)), - t); // transform local t to global t - parameterValues.push_back(w); - } - // End search max curvature point - } - // Delete duplicate of parameterValues - // Because some max cuvature point can coincide with the corner point - if ((int)parameterValues.size() > 1) { - std::sort(parameterValues.begin(), parameterValues.end()); - parameterValues.erase( - std::unique(parameterValues.begin(), parameterValues.end()), - parameterValues.end()); - } -} - -static void addStroke(TTool::Application *application, const TVectorImageP &vi, - TStroke *stroke, bool breakAngles, bool frameCreated, - bool levelCreated, TXshSimpleLevel *sLevel = NULL, - TFrameId fid = TFrameId::NO_FRAME) { - QMutexLocker lock(vi->getMutex()); - - if (application->getCurrentObject()->isSpline()) { - application->getCurrentXsheet()->notifyXsheetChanged(); - return; - } - - std::vector corners; - std::vector strokes; - - const float angoloLim = - 1; // Value (radians) of the Corner between two tangent vector. - // Up this value the two corner can be considered angular. - const float curvMaxLim = 0.8; // Value of the max curvature. - // Up this value the point can be considered a max curvature point. - - findMaxCurvPoints(stroke, angoloLim, curvMaxLim, corners); - TXshSimpleLevel *sl; - if (!sLevel) { - sl = application->getCurrentLevel()->getSimpleLevel(); - } else { - sl = sLevel; - } - TFrameId id = application->getCurrentTool()->getTool()->getCurrentFid(); - if (id == TFrameId::NO_FRAME && fid != TFrameId::NO_FRAME) id = fid; - if (!corners.empty()) { - if (breakAngles) - split(stroke, corners, strokes); - else - strokes.push_back(new TStroke(*stroke)); - - int n = strokes.size(); - - TUndoManager::manager()->beginBlock(); - for (int i = 0; i < n; i++) { - std::vector *fillInformation = - new std::vector; - ImageUtils::getFillingInformationOverlappingArea(vi, *fillInformation, - stroke->getBBox()); - TStroke *str = new TStroke(*strokes[i]); - vi->addStroke(str); - TUndoManager::manager()->add(new UndoPencil(str, fillInformation, sl, id, - frameCreated, levelCreated)); - } - TUndoManager::manager()->endBlock(); - } else { - std::vector *fillInformation = - new std::vector; - ImageUtils::getFillingInformationOverlappingArea(vi, *fillInformation, - stroke->getBBox()); - TStroke *str = new TStroke(*stroke); - vi->addStroke(str); - TUndoManager::manager()->add(new UndoPencil(str, fillInformation, sl, id, - frameCreated, levelCreated)); - } - - // Update regions. It will call roundStroke() in - // TVectorImage::Imp::findIntersections(). - // roundStroke() will slightly modify all the stroke positions. - // It is needed to update information for Fill Check. - vi->findRegions(); - - for (int k = 0; k < (int)strokes.size(); k++) delete strokes[k]; - strokes.clear(); - - application->getCurrentTool()->getTool()->notifyImageChanged(); -} - -//------------------------------------------------------------------- -// -// Gennaro: end -// -//------------------------------------------------------------------- - -//=================================================================== -// -// Helper functions and classes -// -//------------------------------------------------------------------- - -namespace { - -//------------------------------------------------------------------- - -void addStrokeToImage(TTool::Application *application, const TVectorImageP &vi, - TStroke *stroke, bool breakAngles, bool frameCreated, - bool levelCreated, TXshSimpleLevel *sLevel = NULL, - TFrameId id = TFrameId::NO_FRAME) { - QMutexLocker lock(vi->getMutex()); - addStroke(application, vi.getPointer(), stroke, breakAngles, frameCreated, - levelCreated, sLevel, id); - // la notifica viene gia fatta da addStroke! - // getApplication()->getCurrentTool()->getTool()->notifyImageChanged(); -} - -//--------------------------------------------------------------------------------------------------------- - -enum DrawOrder { OverAll = 0, UnderAll, PaletteOrder }; - -void getAboveStyleIdSet(int styleId, TPaletteP palette, - QSet &aboveStyles) { - if (!palette) return; - for (int p = 0; p < palette->getPageCount(); p++) { - TPalette::Page *page = palette->getPage(p); - for (int s = 0; s < page->getStyleCount(); s++) { - int tmpId = page->getStyleId(s); - if (tmpId == styleId) return; - if (tmpId != 0) aboveStyles.insert(tmpId); - } - } -} - -//========================================================================================================= - -class RasterBrushUndo final : public TRasterUndo { - std::vector m_points; - int m_styleId; - bool m_selective; - bool m_isPaletteOrder; - bool m_isPencil; - -public: - RasterBrushUndo(TTileSetCM32 *tileSet, const std::vector &points, - int styleId, bool selective, TXshSimpleLevel *level, - const TFrameId &frameId, bool isPencil, bool isFrameCreated, - bool isLevelCreated, bool isPaletteOrder) - : TRasterUndo(tileSet, level, frameId, isFrameCreated, isLevelCreated, 0) - , m_points(points) - , m_styleId(styleId) - , m_selective(selective) - , m_isPencil(isPencil) - , m_isPaletteOrder(isPaletteOrder) {} - - void redo() const override { - insertLevelAndFrameIfNeeded(); - TToonzImageP image = getImage(); - TRasterCM32P ras = image->getRaster(); - RasterStrokeGenerator m_rasterTrack(ras, BRUSH, NONE, m_styleId, - m_points[0], m_selective, 0, - !m_isPencil, m_isPaletteOrder); - if (m_isPaletteOrder) { - QSet aboveStyleIds; - getAboveStyleIdSet(m_styleId, image->getPalette(), aboveStyleIds); - m_rasterTrack.setAboveStyleIds(aboveStyleIds); - } - m_rasterTrack.setPointsSequence(m_points); - m_rasterTrack.generateStroke(m_isPencil); - image->setSavebox(image->getSavebox() + - m_rasterTrack.getBBox(m_rasterTrack.getPointsSequence())); - ToolUtils::updateSaveBox(); - TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); - notifyImageChanged(); - } - - int getSize() const override { - return sizeof(*this) + TRasterUndo::getSize(); - } - QString getToolName() override { return QString("Brush Tool"); } - int getHistoryType() override { return HistoryType::BrushTool; } -}; - -//========================================================================================================= - -class RasterBluredBrushUndo final : public TRasterUndo { - std::vector m_points; - int m_styleId; - DrawOrder m_drawOrder; - int m_maxThick; - double m_hardness; - -public: - RasterBluredBrushUndo(TTileSetCM32 *tileSet, - const std::vector &points, int styleId, - DrawOrder drawOrder, TXshSimpleLevel *level, - const TFrameId &frameId, int maxThick, double hardness, - bool isFrameCreated, bool isLevelCreated) - : TRasterUndo(tileSet, level, frameId, isFrameCreated, isLevelCreated, 0) - , m_points(points) - , m_styleId(styleId) - , m_drawOrder(drawOrder) - , m_maxThick(maxThick) - , m_hardness(hardness) {} - - void redo() const override { - if (m_points.size() == 0) return; - insertLevelAndFrameIfNeeded(); - TToonzImageP image = getImage(); - TRasterCM32P ras = image->getRaster(); - TRasterCM32P backupRas = ras->clone(); - TRaster32P workRaster(ras->getSize()); - QRadialGradient brushPad = ToolUtils::getBrushPad(m_maxThick, m_hardness); - workRaster->clear(); - BluredBrush brush(workRaster, m_maxThick, brushPad, false); - - if (m_drawOrder == PaletteOrder) { - QSet aboveStyleIds; - getAboveStyleIdSet(m_styleId, image->getPalette(), aboveStyleIds); - brush.setAboveStyleIds(aboveStyleIds); - } - - std::vector points; - points.push_back(m_points[0]); - TRect bbox = brush.getBoundFromPoints(points); - brush.addPoint(m_points[0], 1); - brush.updateDrawing(ras, ras, bbox, m_styleId, (int)m_drawOrder); - if (m_points.size() > 1) { - points.clear(); - points.push_back(m_points[0]); - points.push_back(m_points[1]); - bbox = brush.getBoundFromPoints(points); - brush.addArc(m_points[0], (m_points[1] + m_points[0]) * 0.5, m_points[1], - 1, 1); - brush.updateDrawing(ras, backupRas, bbox, m_styleId, (int)m_drawOrder); - int i; - for (i = 1; i + 2 < (int)m_points.size(); i = i + 2) { - points.clear(); - points.push_back(m_points[i]); - points.push_back(m_points[i + 1]); - points.push_back(m_points[i + 2]); - bbox = brush.getBoundFromPoints(points); - brush.addArc(m_points[i], m_points[i + 1], m_points[i + 2], 1, 1); - brush.updateDrawing(ras, backupRas, bbox, m_styleId, (int)m_drawOrder); - } - } - ToolUtils::updateSaveBox(); - TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); - notifyImageChanged(); - } - - int getSize() const override { - return sizeof(*this) + TRasterUndo::getSize(); - } - - QString getToolName() override { return QString("Brush Tool"); } - int getHistoryType() override { return HistoryType::BrushTool; } -}; - -//========================================================================================================= - -double computeThickness(double pressure, const TDoublePairProperty &property, - bool isPath) { - if (isPath) return 0.0; - double t = pressure * pressure * pressure; - double thick0 = property.getValue().first; - double thick1 = property.getValue().second; - if (thick1 < 0.0001) thick0 = thick1 = 0.0; - return (thick0 + (thick1 - thick0) * t) * 0.5; -} - -//--------------------------------------------------------------------------------------------------------- - -int computeThickness(double pressure, const TIntPairProperty &property, - bool isPath) { - if (isPath) return 0.0; - double t = pressure * pressure * pressure; - int thick0 = property.getValue().first; - int thick1 = property.getValue().second; - return tround(thick0 + (thick1 - thick0) * t); -} - -} // namespace - -//-------------------------------------------------------------------------------------------------- - -static void CatmullRomInterpolate(const TThickPoint &P0, const TThickPoint &P1, - const TThickPoint &P2, const TThickPoint &P3, - int samples, - std::vector &points) { - double x0 = P1.x; - double x1 = (-P0.x + P2.x) * 0.5f; - double x2 = P0.x - 2.5f * P1.x + 2.0f * P2.x - 0.5f * P3.x; - double x3 = -0.5f * P0.x + 1.5f * P1.x - 1.5f * P2.x + 0.5f * P3.x; - - double y0 = P1.y; - double y1 = (-P0.y + P2.y) * 0.5f; - double y2 = P0.y - 2.5f * P1.y + 2.0f * P2.y - 0.5f * P3.y; - double y3 = -0.5f * P0.y + 1.5f * P1.y - 1.5f * P2.y + 0.5f * P3.y; - - double z0 = P1.thick; - double z1 = (-P0.thick + P2.thick) * 0.5f; - double z2 = P0.thick - 2.5f * P1.thick + 2.0f * P2.thick - 0.5f * P3.thick; - double z3 = - -0.5f * P0.thick + 1.5f * P1.thick - 1.5f * P2.thick + 0.5f * P3.thick; - - for (int i = 1; i <= samples; ++i) { - double t = i / (double)(samples + 1); - double t2 = t * t; - double t3 = t2 * t; - TThickPoint p; - p.x = x0 + x1 * t + x2 * t2 + x3 * t3; - p.y = y0 + y1 * t + y2 * t2 + y3 * t3; - p.thick = z0 + z1 * t + z2 * t2 + z3 * t3; - points.push_back(p); - } -} - -//-------------------------------------------------------------------------------------------------- - -static void Smooth(std::vector &points, int radius) { - int n = (int)points.size(); - if (radius < 1 || n < 3) { - return; - } - - std::vector result; - - float d = 1.0f / (radius * 2 + 1); - - for (int i = 1; i < n - 1; ++i) { - int lower = i - radius; - int upper = i + radius; - - TThickPoint total; - total.x = 0; - total.y = 0; - total.thick = 0; - - for (int j = lower; j <= upper; ++j) { - int idx = j; - if (idx < 0) { - idx = 0; - } else if (idx >= n) { - idx = n - 1; - } - total.x += points[idx].x; - total.y += points[idx].y; - total.thick += points[idx].thick; - } - - total.x *= d; - total.y *= d; - total.thick *= d; - result.push_back(total); - } - - for (int i = 1; i < n - 1; ++i) { - points[i].x = result[i - 1].x; - points[i].y = result[i - 1].y; - points[i].thick = result[i - 1].thick; - } - - if (points.size() >= 3) { - std::vector pts; - CatmullRomInterpolate(points[0], points[0], points[1], points[2], 10, pts); - std::vector::iterator it = points.begin(); - points.insert(it, pts.begin(), pts.end()); - - pts.clear(); - CatmullRomInterpolate(points[n - 3], points[n - 2], points[n - 1], - points[n - 1], 10, pts); - it = points.begin(); - it += n - 1; - points.insert(it, pts.begin(), pts.end()); - } -} - -//-------------------------------------------------------------------------------------------------- - -void SmoothStroke::beginStroke(int smooth) { - m_smooth = smooth; - m_outputIndex = 0; - m_readIndex = -1; - m_rawPoints.clear(); - m_outputPoints.clear(); -} - -//-------------------------------------------------------------------------------------------------- - -void SmoothStroke::addPoint(const TThickPoint &point) { - if (m_rawPoints.size() > 0 && m_rawPoints.back().x == point.x && - m_rawPoints.back().y == point.y) { - return; - } - m_rawPoints.push_back(point); - generatePoints(); -} - -//-------------------------------------------------------------------------------------------------- - -void SmoothStroke::endStroke() { - generatePoints(); - // force enable the output all segments - m_outputIndex = m_outputPoints.size() - 1; -} - -//-------------------------------------------------------------------------------------------------- - -void SmoothStroke::clearPoints() { - m_outputIndex = 0; - m_readIndex = -1; - m_outputPoints.clear(); - m_rawPoints.clear(); -} - -//-------------------------------------------------------------------------------------------------- - -void SmoothStroke::getSmoothPoints(std::vector &smoothPoints) { - int n = m_outputPoints.size(); - for (int i = m_readIndex + 1; i <= m_outputIndex && i < n; ++i) { - smoothPoints.push_back(m_outputPoints[i]); - } - m_readIndex = m_outputIndex; -} - -//-------------------------------------------------------------------------------------------------- - -void SmoothStroke::generatePoints() { - int n = (int)m_rawPoints.size(); - if (n == 0) { - return; - } - - // if m_smooth = 0, then skip whole smoothing process - if (m_smooth == 0) { - for (int i = m_outputIndex; i < (int)m_outputPoints.size(); ++i) { - if (m_outputPoints[i] != m_rawPoints[i]) { - break; - } - ++m_outputIndex; - } - m_outputPoints = m_rawPoints; - return; - } - - std::vector smoothedPoints; - // Add more stroke samples before applying the smoothing - // This is because the raw inputs points are too few to support smooth result, - // especially on stroke ends - smoothedPoints.push_back(m_rawPoints.front()); - for (int i = 1; i < n; ++i) { - const TThickPoint &p1 = m_rawPoints[i - 1]; - const TThickPoint &p2 = m_rawPoints[i]; - const TThickPoint &p0 = i - 2 >= 0 ? m_rawPoints[i - 2] : p1; - const TThickPoint &p3 = i + 1 < n ? m_rawPoints[i + 1] : p2; - - int samples = 8; - CatmullRomInterpolate(p0, p1, p2, p3, samples, smoothedPoints); - smoothedPoints.push_back(p2); - } - // Apply the 1D box filter - // Multiple passes result in better quality and fix the stroke ends break - // issue - for (int i = 0; i < 3; ++i) { - Smooth(smoothedPoints, m_smooth); - } - // Compare the new smoothed stroke with old one - // Enable the output for unchanged parts - int outputNum = (int)m_outputPoints.size(); - for (int i = m_outputIndex; i < outputNum; ++i) { - if (m_outputPoints[i] != smoothedPoints[i]) { - break; - } - ++m_outputIndex; - } - m_outputPoints = smoothedPoints; -} - -//=================================================================== -// -// BrushTool -// -//----------------------------------------------------------------------------- - -BrushTool::BrushTool(std::string name, int targetType) - : TTool(name) - , m_thickness("Size", 0, 100, 0, 5) - , m_rasThickness("Size", 1, 100, 1, 5) - , m_accuracy("Accuracy:", 1, 100, 20) - , m_smooth("Smooth:", 0, 50, 0) - , m_hardness("Hardness:", 0, 100, 100) - , m_preset("Preset:") - , m_drawOrder("Draw Order:") - , m_breakAngles("Break", true) - , m_pencil("Pencil", false) - , m_pressure("Pressure", true) - , m_capStyle("Cap") - , m_joinStyle("Join") - , m_miterJoinLimit("Miter:", 0, 100, 4) - , m_rasterTrack(0) - , m_styleId(0) - , m_modifiedRegion() - , m_bluredBrush(0) - , m_active(false) - , m_enabled(false) - , m_isPrompting(false) - , m_firstTime(true) - , m_firstFrameRange(true) - , m_presetsLoaded(false) - , m_frameRange("Range:") - , m_snap("Snap", false) - , m_snapSensitivity("Sensitivity:") - , m_targetType(targetType) - , m_workingFrameId(TFrameId()) { - bind(targetType); - - if (targetType & TTool::Vectors) { - m_prop[0].bind(m_thickness); - m_prop[0].bind(m_accuracy); - m_prop[0].bind(m_smooth); - m_prop[0].bind(m_breakAngles); - m_breakAngles.setId("BreakSharpAngles"); - } - - if (targetType & TTool::ToonzImage) { - m_prop[0].bind(m_rasThickness); - m_prop[0].bind(m_hardness); - m_prop[0].bind(m_smooth); - m_prop[0].bind(m_drawOrder); - m_prop[0].bind(m_pencil); - m_pencil.setId("PencilMode"); - - m_drawOrder.addValue(L"Over All"); - m_drawOrder.addValue(L"Under All"); - m_drawOrder.addValue(L"Palette Order"); - m_drawOrder.setId("DrawOrder"); - } - - m_prop[0].bind(m_pressure); - - if (targetType & TTool::Vectors) { - m_frameRange.addValue(L"Off"); - m_frameRange.addValue(LINEAR_WSTR); - m_frameRange.addValue(EASEIN_WSTR); - m_frameRange.addValue(EASEOUT_WSTR); - m_frameRange.addValue(EASEINOUT_WSTR); - m_prop[0].bind(m_frameRange); - m_frameRange.setId("FrameRange"); - m_prop[0].bind(m_snap); - m_snap.setId("Snap"); - m_snapSensitivity.addValue(LOW_WSTR); - m_snapSensitivity.addValue(MEDIUM_WSTR); - m_snapSensitivity.addValue(HIGH_WSTR); - m_prop[0].bind(m_snapSensitivity); - m_snapSensitivity.setId("SnapSensitivity"); - } - - m_prop[0].bind(m_preset); - m_preset.setId("BrushPreset"); - m_preset.addValue(CUSTOM_WSTR); - m_pressure.setId("PressureSensitivity"); - - if (targetType & TTool::Vectors) { - m_capStyle.addValue(BUTT_WSTR, QString::fromStdWString(BUTT_WSTR)); - m_capStyle.addValue(ROUNDC_WSTR, QString::fromStdWString(ROUNDC_WSTR)); - m_capStyle.addValue(PROJECTING_WSTR, - QString::fromStdWString(PROJECTING_WSTR)); - m_capStyle.setId("Cap"); - m_prop[1].bind(m_capStyle); - - m_joinStyle.addValue(MITER_WSTR, QString::fromStdWString(MITER_WSTR)); - m_joinStyle.addValue(ROUNDJ_WSTR, QString::fromStdWString(ROUNDJ_WSTR)); - m_joinStyle.addValue(BEVEL_WSTR, QString::fromStdWString(BEVEL_WSTR)); - m_joinStyle.setId("Join"); - m_prop[1].bind(m_joinStyle); - - m_miterJoinLimit.setId("Miter"); - m_prop[1].bind(m_miterJoinLimit); - } -} - -//------------------------------------------------------------------------------------------------------- - -ToolOptionsBox *BrushTool::createOptionsBox() { - TPaletteHandle *currPalette = - TTool::getApplication()->getPaletteController()->getCurrentLevelPalette(); - ToolHandle *currTool = TTool::getApplication()->getCurrentTool(); - return new BrushToolOptionsBox(0, this, currPalette, currTool); -} - -//------------------------------------------------------------------------------------------------------- - -void BrushTool::drawLine(const TPointD &point, const TPointD ¢re, - bool horizontal, bool isDecimal) { - if (!isDecimal) { - if (horizontal) { - tglDrawSegment(TPointD(point.x - 1.5, point.y + 0.5) + centre, - TPointD(point.x - 0.5, point.y + 0.5) + centre); - tglDrawSegment(TPointD(point.y - 0.5, -point.x + 1.5) + centre, - TPointD(point.y - 0.5, -point.x + 0.5) + centre); - tglDrawSegment(TPointD(-point.x + 0.5, -point.y + 0.5) + centre, - TPointD(-point.x - 0.5, -point.y + 0.5) + centre); - tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre, - TPointD(-point.y - 0.5, point.x + 0.5) + centre); - - tglDrawSegment(TPointD(point.y - 0.5, point.x + 0.5) + centre, - TPointD(point.y - 0.5, point.x - 0.5) + centre); - tglDrawSegment(TPointD(point.x - 0.5, -point.y + 0.5) + centre, - TPointD(point.x - 1.5, -point.y + 0.5) + centre); - tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre, - TPointD(-point.y - 0.5, -point.x + 1.5) + centre); - tglDrawSegment(TPointD(-point.x - 0.5, point.y + 0.5) + centre, - TPointD(-point.x + 0.5, point.y + 0.5) + centre); - } else { - tglDrawSegment(TPointD(point.x - 1.5, point.y + 1.5) + centre, - TPointD(point.x - 1.5, point.y + 0.5) + centre); - tglDrawSegment(TPointD(point.x - 1.5, point.y + 0.5) + centre, - TPointD(point.x - 0.5, point.y + 0.5) + centre); - tglDrawSegment(TPointD(point.y + 0.5, -point.x + 1.5) + centre, - TPointD(point.y - 0.5, -point.x + 1.5) + centre); - tglDrawSegment(TPointD(point.y - 0.5, -point.x + 1.5) + centre, - TPointD(point.y - 0.5, -point.x + 0.5) + centre); - tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 0.5) + centre, - TPointD(-point.x + 0.5, -point.y + 0.5) + centre); - tglDrawSegment(TPointD(-point.x + 0.5, -point.y + 0.5) + centre, - TPointD(-point.x - 0.5, -point.y + 0.5) + centre); - tglDrawSegment(TPointD(-point.y - 1.5, point.x - 0.5) + centre, - TPointD(-point.y - 0.5, point.x - 0.5) + centre); - tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre, - TPointD(-point.y - 0.5, point.x + 0.5) + centre); - - tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre, - TPointD(point.y - 0.5, point.x - 0.5) + centre); - tglDrawSegment(TPointD(point.y - 0.5, point.x - 0.5) + centre, - TPointD(point.y - 0.5, point.x + 0.5) + centre); - tglDrawSegment(TPointD(point.x - 1.5, -point.y - 0.5) + centre, - TPointD(point.x - 1.5, -point.y + 0.5) + centre); - tglDrawSegment(TPointD(point.x - 1.5, -point.y + 0.5) + centre, - TPointD(point.x - 0.5, -point.y + 0.5) + centre); - tglDrawSegment(TPointD(-point.y - 1.5, -point.x + 1.5) + centre, - TPointD(-point.y - 0.5, -point.x + 1.5) + centre); - tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 1.5) + centre, - TPointD(-point.y - 0.5, -point.x + 0.5) + centre); - tglDrawSegment(TPointD(-point.x + 0.5, point.y + 1.5) + centre, - TPointD(-point.x + 0.5, point.y + 0.5) + centre); - tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre, - TPointD(-point.x - 0.5, point.y + 0.5) + centre); - } - } else { - if (horizontal) { - tglDrawSegment(TPointD(point.x - 0.5, point.y + 0.5) + centre, - TPointD(point.x + 0.5, point.y + 0.5) + centre); - tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre, - TPointD(point.y + 0.5, point.x + 0.5) + centre); - tglDrawSegment(TPointD(point.y + 0.5, -point.x + 0.5) + centre, - TPointD(point.y + 0.5, -point.x - 0.5) + centre); - tglDrawSegment(TPointD(point.x + 0.5, -point.y - 0.5) + centre, - TPointD(point.x - 0.5, -point.y - 0.5) + centre); - tglDrawSegment(TPointD(-point.x - 0.5, -point.y - 0.5) + centre, - TPointD(-point.x + 0.5, -point.y - 0.5) + centre); - tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre, - TPointD(-point.y - 0.5, -point.x - 0.5) + centre); - tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre, - TPointD(-point.y - 0.5, point.x + 0.5) + centre); - tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre, - TPointD(-point.x - 0.5, point.y + 0.5) + centre); - } else { - tglDrawSegment(TPointD(point.x - 0.5, point.y + 1.5) + centre, - TPointD(point.x - 0.5, point.y + 0.5) + centre); - tglDrawSegment(TPointD(point.x - 0.5, point.y + 0.5) + centre, - TPointD(point.x + 0.5, point.y + 0.5) + centre); - tglDrawSegment(TPointD(point.y + 1.5, point.x - 0.5) + centre, - TPointD(point.y + 0.5, point.x - 0.5) + centre); - tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre, - TPointD(point.y + 0.5, point.x + 0.5) + centre); - tglDrawSegment(TPointD(point.y + 1.5, -point.x + 0.5) + centre, - TPointD(point.y + 0.5, -point.x + 0.5) + centre); - tglDrawSegment(TPointD(point.y + 0.5, -point.x + 0.5) + centre, - TPointD(point.y + 0.5, -point.x - 0.5) + centre); - tglDrawSegment(TPointD(point.x - 0.5, -point.y - 1.5) + centre, - TPointD(point.x - 0.5, -point.y - 0.5) + centre); - tglDrawSegment(TPointD(point.x - 0.5, -point.y - 0.5) + centre, - TPointD(point.x + 0.5, -point.y - 0.5) + centre); - - tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 1.5) + centre, - TPointD(-point.x + 0.5, -point.y - 0.5) + centre); - tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 0.5) + centre, - TPointD(-point.x - 0.5, -point.y - 0.5) + centre); - tglDrawSegment(TPointD(-point.y - 1.5, -point.x + 0.5) + centre, - TPointD(-point.y - 0.5, -point.x + 0.5) + centre); - tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre, - TPointD(-point.y - 0.5, -point.x - 0.5) + centre); - tglDrawSegment(TPointD(-point.y - 1.5, point.x - 0.5) + centre, - TPointD(-point.y - 0.5, point.x - 0.5) + centre); - tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre, - TPointD(-point.y - 0.5, point.x + 0.5) + centre); - tglDrawSegment(TPointD(-point.x + 0.5, point.y + 1.5) + centre, - TPointD(-point.x + 0.5, point.y + 0.5) + centre); - tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre, - TPointD(-point.x - 0.5, point.y + 0.5) + centre); - } - } -} - -//------------------------------------------------------------------------------------------------------- - -void BrushTool::drawEmptyCircle(TPointD pos, int thick, bool isLxEven, - bool isLyEven, bool isPencil) { - if (isLxEven) pos.x += 0.5; - if (isLyEven) pos.y += 0.5; - - if (!isPencil) - tglDrawCircle(pos, (thick + 1) * 0.5); - else { - int x = 0, y = tround((thick * 0.5) - 0.5); - int d = 3 - 2 * (int)(thick * 0.5); - bool horizontal = true, isDecimal = thick % 2 != 0; - drawLine(TPointD(x, y), pos, horizontal, isDecimal); - while (y > x) { - if (d < 0) { - d = d + 4 * x + 6; - horizontal = true; - } else { - d = d + 4 * (x - y) + 10; - horizontal = false; - y--; - } - x++; - drawLine(TPointD(x, y), pos, horizontal, isDecimal); - } - } -} - -//------------------------------------------------------------------------------------------------------- - -void BrushTool::updateTranslation() { - m_thickness.setQStringName(tr("Size")); - m_rasThickness.setQStringName(tr("Size")); - m_hardness.setQStringName(tr("Hardness:")); - m_accuracy.setQStringName(tr("Accuracy:")); - m_smooth.setQStringName(tr("Smooth:")); - m_drawOrder.setQStringName(tr("Draw Order:")); - if (m_targetType & TTool::ToonzImage) { - m_drawOrder.setItemUIName(L"Over All", tr("Over All")); - m_drawOrder.setItemUIName(L"Under All", tr("Under All")); - m_drawOrder.setItemUIName(L"Palette Order", tr("Palette Order")); - } - // m_filled.setQStringName(tr("Filled")); - m_preset.setQStringName(tr("Preset:")); - m_preset.setItemUIName(CUSTOM_WSTR, tr("")); - m_breakAngles.setQStringName(tr("Break")); - m_pencil.setQStringName(tr("Pencil")); - m_pressure.setQStringName(tr("Pressure")); - m_capStyle.setQStringName(tr("Cap")); - m_joinStyle.setQStringName(tr("Join")); - m_miterJoinLimit.setQStringName(tr("Miter:")); - m_frameRange.setQStringName(tr("Range:")); - m_snap.setQStringName(tr("Snap")); - m_snapSensitivity.setQStringName(""); - if (m_targetType & TTool::Vectors) { - m_frameRange.setItemUIName(L"Off", tr("Off")); - m_frameRange.setItemUIName(LINEAR_WSTR, tr("Linear")); - m_frameRange.setItemUIName(EASEIN_WSTR, tr("In")); - m_frameRange.setItemUIName(EASEOUT_WSTR, tr("Out")); - m_frameRange.setItemUIName(EASEINOUT_WSTR, tr("In&Out")); - m_snapSensitivity.setItemUIName(LOW_WSTR, tr("Low")); - m_snapSensitivity.setItemUIName(MEDIUM_WSTR, tr("Med")); - m_snapSensitivity.setItemUIName(HIGH_WSTR, tr("High")); - m_capStyle.setItemUIName(BUTT_WSTR, tr("Butt cap")); - m_capStyle.setItemUIName(ROUNDC_WSTR, tr("Round cap")); - m_capStyle.setItemUIName(PROJECTING_WSTR, tr("Projecting cap")); - m_joinStyle.setItemUIName(MITER_WSTR, tr("Miter join")); - m_joinStyle.setItemUIName(ROUNDJ_WSTR, tr("Round join")); - m_joinStyle.setItemUIName(BEVEL_WSTR, tr("Bevel join")); - } -} - -//--------------------------------------------------------------------------------------------------- - -void BrushTool::updateWorkAndBackupRasters(const TRect &rect) { - TToonzImageP ti = TImageP(getImage(false, 1)); - if (!ti) return; - - TRasterCM32P ras = ti->getRaster(); - - TRect _rect = rect * ras->getBounds(); - TRect _lastRect = m_lastRect * ras->getBounds(); - - if (_rect.isEmpty()) return; - - if (m_lastRect.isEmpty()) { - m_workRas->extract(_rect)->clear(); - m_backupRas->extract(_rect)->copy(ras->extract(_rect)); - return; - } - - QList rects = ToolUtils::splitRect(_rect, _lastRect); - for (int i = 0; i < rects.size(); i++) { - m_workRas->extract(rects[i])->clear(); - m_backupRas->extract(rects[i])->copy(ras->extract(rects[i])); - } -} - -//--------------------------------------------------------------------------------------------------- - -void BrushTool::onActivate() { - if (m_firstTime) { - m_thickness.setValue( - TDoublePairProperty::Value(VectorBrushMinSize, VectorBrushMaxSize)); - m_rasThickness.setValue( - TDoublePairProperty::Value(RasterBrushMinSize, RasterBrushMaxSize)); - if (m_targetType & TTool::Vectors) { - m_capStyle.setIndex(VectorCapStyle); - m_joinStyle.setIndex(VectorJoinStyle); - m_miterJoinLimit.setValue(VectorMiterValue); - m_breakAngles.setValue(BrushBreakSharpAngles ? 1 : 0); - m_accuracy.setValue(BrushAccuracy); - } - if (m_targetType & TTool::ToonzImage) { - m_drawOrder.setIndex(BrushDrawOrder); - m_pencil.setValue(RasterBrushPencilMode ? 1 : 0); - m_hardness.setValue(RasterBrushHardness); - } - m_pressure.setValue(BrushPressureSensitivity ? 1 : 0); - m_firstTime = false; - m_smooth.setValue(BrushSmooth); - if (m_targetType & TTool::Vectors) { - m_frameRange.setIndex(VectorBrushFrameRange); - m_snap.setValue(VectorBrushSnap); - m_snapSensitivity.setIndex(VectorBrushSnapSensitivity); - switch (VectorBrushSnapSensitivity) { - case 0: - m_minDistance2 = SNAPPING_LOW; - break; - case 1: - m_minDistance2 = SNAPPING_MEDIUM; - break; - case 2: - m_minDistance2 = SNAPPING_HIGH; - break; - } - } - } - if (m_targetType & TTool::ToonzImage) { - m_brushPad = ToolUtils::getBrushPad(m_rasThickness.getValue().second, - m_hardness.getValue() * 0.01); - setWorkAndBackupImages(); - } - resetFrameRange(); - // TODO:app->editImageOrSpline(); -} - -//-------------------------------------------------------------------------------------------------- - -void BrushTool::onDeactivate() { - /*--- - * ドラッグ中にツールが切り替わった場合に備え、onDeactivateにもMouseReleaseと同じ処理を行う - * ---*/ - if (m_tileSaver && !m_isPath) { - bool isValid = m_enabled && m_active; - m_enabled = false; - if (isValid) { - TImageP image = getImage(true); - if (TToonzImageP ti = image) - finishRasterBrush(m_mousePos, - 1); /*-- 最後のストロークの筆圧は1とする --*/ - } - } - m_workRas = TRaster32P(); - m_backupRas = TRasterCM32P(); - resetFrameRange(); -} - -//-------------------------------------------------------------------------------------------------- - -bool BrushTool::preLeftButtonDown() { - touchImage(); - if (m_isFrameCreated) { - setWorkAndBackupImages(); - // When the xsheet frame is selected, whole viewer will be updated from - // SceneViewer::onXsheetChanged() on adding a new frame. - // We need to take care of a case when the level frame is selected. - if (m_application->getCurrentFrame()->isEditingLevel()) invalidate(); - } - return true; -} - -//-------------------------------------------------------------------------------------------------- - -void BrushTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { - TTool::Application *app = TTool::getApplication(); - if (!app) return; - - int col = app->getCurrentColumn()->getColumnIndex(); - m_isPath = app->getCurrentObject()->isSpline(); - m_enabled = col >= 0 || m_isPath; - // todo: gestire autoenable - if (!m_enabled) return; - if (!m_isPath) { - m_currentColor = TPixel32::Black; - m_active = !!getImage(true); - if (!m_active) { - m_active = !!touchImage(); - } - if (!m_active) return; - - if (m_active) { - // nel caso che il colore corrente sia un cleanup/studiopalette color - // oppure il colore di un colorfield - m_styleId = app->getCurrentLevelStyleIndex(); - TColorStyle *cs = app->getCurrentLevelStyle(); - if (cs) { - TRasterStyleFx *rfx = cs ? cs->getRasterStyleFx() : 0; - m_active = - cs != 0 && (cs->isStrokeStyle() || (rfx && rfx->isInkStyle())); - m_currentColor = cs->getAverageColor(); - m_currentColor.m = 255; - } else { - m_styleId = 1; - m_currentColor = TPixel32::Black; - } - } - } else { - m_currentColor = TPixel32::Red; - m_active = true; - } - // assert(0<=m_styleId && m_styleId<2); - TImageP img = getImage(true); - TToonzImageP ri(img); - if (ri) { - TRasterCM32P ras = ri->getRaster(); - if (ras) { - TPointD rasCenter = ras->getCenterD(); - m_tileSet = new TTileSetCM32(ras->getSize()); - m_tileSaver = new TTileSaverCM32(ras, m_tileSet); - double maxThick = m_rasThickness.getValue().second; - double thickness = - (m_pressure.getValue() || m_isPath) - ? computeThickness(e.m_pressure, m_rasThickness, m_isPath) * 2 - : maxThick; - - /*--- ストロークの最初にMaxサイズの円が描かれてしまう不具合を防止する - * ---*/ - if (m_pressure.getValue() && e.m_pressure == 1.0) - thickness = m_rasThickness.getValue().first; - - TPointD halfThick(maxThick * 0.5, maxThick * 0.5); - TRectD invalidateRect(pos - halfThick, pos + halfThick); - TPointD dpi; - ri->getDpi(dpi.x, dpi.y); - TRectD previousTipRect(m_brushPos - halfThick, m_brushPos + halfThick); - if (dpi.x > Stage::inch || dpi.y > Stage::inch) - previousTipRect *= dpi.x / Stage::inch; - invalidateRect += previousTipRect; - - // if the drawOrder mode = "Palette Order", - // get styleId list which is above the current style in the palette - DrawOrder drawOrder = (DrawOrder)m_drawOrder.getIndex(); - QSet aboveStyleIds; - if (drawOrder == PaletteOrder) { - getAboveStyleIdSet(m_styleId, ri->getPalette(), aboveStyleIds); - } - - if (m_hardness.getValue() == 100 || m_pencil.getValue()) { - /*-- Pencilモードでなく、Hardness=100 の場合のブラシサイズを1段階下げる - * --*/ - if (!m_pencil.getValue()) thickness -= 1.0; - - TThickPoint thickPoint(pos + convert(ras->getCenter()), thickness); - m_rasterTrack = new RasterStrokeGenerator( - ras, BRUSH, NONE, m_styleId, thickPoint, drawOrder != OverAll, 0, - !m_pencil.getValue(), drawOrder == PaletteOrder); - - if (drawOrder == PaletteOrder) - m_rasterTrack->setAboveStyleIds(aboveStyleIds); - - m_tileSaver->save(m_rasterTrack->getLastRect()); - m_rasterTrack->generateLastPieceOfStroke(m_pencil.getValue()); - - std::vector pts; - if (m_smooth.getValue() == 0) { - pts.push_back(thickPoint); - } else { - m_smoothStroke.beginStroke(m_smooth.getValue()); - m_smoothStroke.addPoint(thickPoint); - m_smoothStroke.getSmoothPoints(pts); - } - } else { - m_points.clear(); - TThickPoint point(pos + rasCenter, thickness); - m_points.push_back(point); - m_bluredBrush = new BluredBrush(m_workRas, maxThick, m_brushPad, false); - - if (drawOrder == PaletteOrder) - m_bluredBrush->setAboveStyleIds(aboveStyleIds); - - m_strokeRect = m_bluredBrush->getBoundFromPoints(m_points); - updateWorkAndBackupRasters(m_strokeRect); - m_tileSaver->save(m_strokeRect); - m_bluredBrush->addPoint(point, 1); - m_bluredBrush->updateDrawing(ri->getRaster(), m_backupRas, m_strokeRect, - m_styleId, drawOrder); - m_lastRect = m_strokeRect; - - std::vector pts; - if (m_smooth.getValue() == 0) { - pts.push_back(point); - } else { - m_smoothStroke.beginStroke(m_smooth.getValue()); - m_smoothStroke.addPoint(point); - m_smoothStroke.getSmoothPoints(pts); - } - } - /*-- 作業中のFidを登録 --*/ - m_workingFrameId = getFrameId(); - - invalidate(invalidateRect.enlarge(2)); - } - } else { // vector happens here - m_track.clear(); - double thickness = - (m_pressure.getValue() || m_isPath) - ? computeThickness(e.m_pressure, m_thickness, m_isPath) - : m_thickness.getValue().second * 0.5; - - /*--- ストロークの最初にMaxサイズの円が描かれてしまう不具合を防止する ---*/ - if (m_pressure.getValue() && e.m_pressure == 1.0) - thickness = m_thickness.getValue().first * 0.5; - m_currThickness = thickness; - m_smoothStroke.beginStroke(m_smooth.getValue()); - - if ((m_targetType & TTool::Vectors) && m_foundFirstSnap) { - addTrackPoint(TThickPoint(m_firstSnapPoint, thickness), - getPixelSize() * getPixelSize()); - } else - addTrackPoint(TThickPoint(pos, thickness), - getPixelSize() * getPixelSize()); - TRectD invalidateRect = m_track.getLastModifiedRegion(); - invalidate(invalidateRect.enlarge(2)); - } - - // updating m_brushPos is needed to refresh viewer properly - m_brushPos = m_mousePos = pos; -} - -//------------------------------------------------------------------------------------------------------------- - -void BrushTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { - if (!m_enabled || !m_active) { - m_brushPos = m_mousePos = pos; - return; - } - - if (TToonzImageP ti = TImageP(getImage(true))) { - TPointD rasCenter = ti->getRaster()->getCenterD(); - int maxThickness = m_rasThickness.getValue().second; - double thickness = - (m_pressure.getValue() || m_isPath) - ? computeThickness(e.m_pressure, m_rasThickness, m_isPath) * 2 - : maxThickness; - TRectD invalidateRect; - if (m_rasterTrack && - (m_hardness.getValue() == 100 || m_pencil.getValue())) { - /*-- Pencilモードでなく、Hardness=100 の場合のブラシサイズを1段階下げる - * --*/ - if (!m_pencil.getValue()) thickness -= 1.0; - - TThickPoint thickPoint(pos + rasCenter, thickness); - std::vector pts; - if (m_smooth.getValue() == 0) { - pts.push_back(thickPoint); - } else { - m_smoothStroke.addPoint(thickPoint); - m_smoothStroke.getSmoothPoints(pts); - } - for (size_t i = 0; i < pts.size(); ++i) { - const TThickPoint &thickPoint = pts[i]; - m_rasterTrack->add(thickPoint); - m_tileSaver->save(m_rasterTrack->getLastRect()); - m_rasterTrack->generateLastPieceOfStroke(m_pencil.getValue()); - std::vector brushPoints = - m_rasterTrack->getPointsSequence(); - int m = (int)brushPoints.size(); - std::vector points; - if (m == 3) { - points.push_back(brushPoints[0]); - points.push_back(brushPoints[1]); - } else { - points.push_back(brushPoints[m - 4]); - points.push_back(brushPoints[m - 3]); - points.push_back(brushPoints[m - 2]); - } - invalidateRect += - ToolUtils::getBounds(points, maxThickness) - rasCenter; - } - } else { - // antialiased brush - assert(m_workRas.getPointer() && m_backupRas.getPointer()); - TThickPoint thickPoint(pos + rasCenter, thickness); - std::vector pts; - if (m_smooth.getValue() == 0) { - pts.push_back(thickPoint); - } else { - m_smoothStroke.addPoint(thickPoint); - m_smoothStroke.getSmoothPoints(pts); - } - for (size_t i = 0; i < pts.size(); ++i) { - TThickPoint old = m_points.back(); - - const TThickPoint &point = pts[i]; - TThickPoint mid((old + point) * 0.5, (point.thick + old.thick) * 0.5); - m_points.push_back(mid); - m_points.push_back(point); - - TRect bbox; - int m = (int)m_points.size(); - std::vector points; - if (m == 3) { - // ho appena cominciato. devo disegnare un segmento - TThickPoint pa = m_points.front(); - points.push_back(pa); - points.push_back(mid); - bbox = m_bluredBrush->getBoundFromPoints(points); - updateWorkAndBackupRasters(bbox + m_lastRect); - m_tileSaver->save(bbox); - m_bluredBrush->addArc(pa, (mid + pa) * 0.5, mid, 1, 1); - m_lastRect += bbox; - } else { - points.push_back(m_points[m - 4]); - points.push_back(old); - points.push_back(mid); - bbox = m_bluredBrush->getBoundFromPoints(points); - updateWorkAndBackupRasters(bbox + m_lastRect); - m_tileSaver->save(bbox); - m_bluredBrush->addArc(m_points[m - 4], old, mid, 1, 1); - m_lastRect += bbox; - } - invalidateRect += - ToolUtils::getBounds(points, maxThickness) - rasCenter; - - m_bluredBrush->updateDrawing(ti->getRaster(), m_backupRas, bbox, - m_styleId, m_drawOrder.getIndex()); - m_strokeRect += bbox; - } - } - - // clear & draw brush tip when drawing smooth stroke - if (m_smooth.getValue() != 0) { - TPointD halfThick(m_maxThick * 0.5, m_maxThick * 0.5); - invalidateRect += TRectD(m_brushPos - halfThick, m_brushPos + halfThick); - invalidateRect += TRectD(pos - halfThick, pos + halfThick); - } - - m_brushPos = m_mousePos = pos; - - invalidate(invalidateRect.enlarge(2)); - } else { - double thickness = - (m_pressure.getValue() || m_isPath) - ? computeThickness(e.m_pressure, m_thickness, m_isPath) - : m_thickness.getValue().second * 0.5; - - TRectD invalidateRect; - TPointD halfThick(m_maxThick * 0.5, m_maxThick * 0.5); - TPointD snapThick(6.0 * m_pixelSize, 6.0 * m_pixelSize); - - // In order to clear the previous brush tip - invalidateRect += TRectD(m_brushPos - halfThick, m_brushPos + halfThick); - - // In order to clear the previous snap indicator - if (m_foundLastSnap) - invalidateRect += - TRectD(m_lastSnapPoint - snapThick, m_lastSnapPoint + snapThick); - - m_currThickness = thickness; - - m_mousePos = pos; - m_lastSnapPoint = pos; - m_foundLastSnap = false; - m_foundFirstSnap = false; - m_snapSelf = false; - m_altPressed = e.isAltPressed() && !e.isCtrlPressed(); - - checkStrokeSnapping(false, m_altPressed); - checkGuideSnapping(false, m_altPressed); - m_brushPos = m_lastSnapPoint; - - if (m_foundLastSnap) - invalidateRect += - TRectD(m_lastSnapPoint - snapThick, m_lastSnapPoint + snapThick); - - if (e.isShiftPressed()) { - m_smoothStroke.clearPoints(); - m_track.add(TThickPoint(m_brushPos, thickness), - getPixelSize() * getPixelSize()); - m_track.removeMiddlePoints(); - invalidateRect += m_track.getModifiedRegion(); - } else if (m_dragDraw) { - addTrackPoint(TThickPoint(pos, thickness), - getPixelSize() * getPixelSize()); - invalidateRect += m_track.getLastModifiedRegion(); - } - - // In order to draw the current brush tip - invalidateRect += TRectD(m_brushPos - halfThick, m_brushPos + halfThick); - - if (!invalidateRect.isEmpty()) invalidate(invalidateRect.enlarge(2)); - } -} - -//--------------------------------------------------------------------------------------------------------------- - -void BrushTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) { - bool isValid = m_enabled && m_active; - m_enabled = false; - - if (!isValid) { - // in case the current frame is moved to empty cell while dragging - if (!m_track.isEmpty()) { - m_track.clear(); - invalidate(); - } - return; - } - - if (m_isPath) { - double error = 20.0 * getPixelSize(); - - TStroke *stroke; - if (e.isShiftPressed()) { - m_track.removeMiddlePoints(); - stroke = m_track.makeStroke(0); - } else { - flushTrackPoint(); - stroke = m_track.makeStroke(error); - } - int points = stroke->getControlPointCount(); - - if (TVectorImageP vi = getImage(true)) { - struct Cleanup { - BrushTool *m_this; - ~Cleanup() { m_this->m_track.clear(), m_this->invalidate(); } - } cleanup = {this}; - - if (!isJustCreatedSpline(vi.getPointer())) { - m_isPrompting = true; - - QString question("Are you sure you want to replace the motion path?"); - int ret = - DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"), 0); - - m_isPrompting = false; - - if (ret == 2 || ret == 0) return; - } - - QMutexLocker lock(vi->getMutex()); - - TUndo *undo = - new UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline()); - - while (vi->getStrokeCount() > 0) vi->deleteStroke(0); - vi->addStroke(stroke, false); - - notifyImageChanged(); - TUndoManager::manager()->add(undo); - } - - return; - } - - TImageP image = getImage(true); - if (TVectorImageP vi = image) { - if (m_track.isEmpty()) { - m_styleId = 0; - m_track.clear(); - return; - } - - if (vi && (m_snap.getValue() != m_altPressed) && m_foundLastSnap) { - addTrackPoint(TThickPoint(m_lastSnapPoint, m_currThickness), - getPixelSize() * getPixelSize()); - } - m_strokeIndex1 = -1; - m_strokeIndex2 = -1; - m_w1 = -1; - m_w2 = -2; - m_foundFirstSnap = false; - m_foundLastSnap = false; - - m_track.filterPoints(); - double error = 30.0 / (1 + 0.5 * m_accuracy.getValue()); - error *= getPixelSize(); - - TStroke *stroke; - if (e.isShiftPressed()) { - m_track.removeMiddlePoints(); - stroke = m_track.makeStroke(0); - } else { - flushTrackPoint(); - stroke = m_track.makeStroke(error); - } - stroke->setStyle(m_styleId); - { - TStroke::OutlineOptions &options = stroke->outlineOptions(); - options.m_capStyle = m_capStyle.getIndex(); - options.m_joinStyle = m_joinStyle.getIndex(); - options.m_miterUpper = m_miterJoinLimit.getValue(); - } - m_styleId = 0; - - QMutexLocker lock(vi->getMutex()); - if (stroke->getControlPointCount() == 3 && - stroke->getControlPoint(0) != - stroke->getControlPoint(2)) // gli stroke con solo 1 chunk vengono - // fatti dal tape tool...e devono venir - // riconosciuti come speciali di - // autoclose proprio dal fatto che - // hanno 1 solo chunk. - stroke->insertControlPoints(0.5); - if (m_frameRange.getIndex()) { - if (m_firstFrameId == -1) { - m_firstStroke = new TStroke(*stroke); - m_firstFrameId = getFrameId(); - TTool::Application *application = TTool::getApplication(); - if (application) { - m_col = application->getCurrentColumn()->getColumnIndex(); - m_firstFrame = application->getCurrentFrame()->getFrame(); - } - m_rangeTrack = m_track; - if (m_firstFrameRange) { - m_veryFirstCol = m_col; - m_veryFirstFrame = m_firstFrame; - m_veryFirstFrameId = m_firstFrameId; - } - } else if (m_firstFrameId == getFrameId()) { - if (m_firstStroke) { - delete m_firstStroke; - m_firstStroke = 0; - } - m_firstStroke = new TStroke(*stroke); - m_rangeTrack = m_track; - } else { - TFrameId currentId = getFrameId(); - int curCol = 0, curFrame = 0; - TTool::Application *application = TTool::getApplication(); - if (application) { - curCol = application->getCurrentColumn()->getColumnIndex(); - curFrame = application->getCurrentFrame()->getFrame(); - } - bool success = - doFrameRangeStrokes(m_firstFrameId, m_firstStroke, getFrameId(), - stroke, m_firstFrameRange); - if (e.isCtrlPressed()) { - if (application) { - if (m_firstFrameId > currentId) { - if (application->getCurrentFrame()->isEditingScene()) { - application->getCurrentColumn()->setColumnIndex(curCol); - application->getCurrentFrame()->setFrame(curFrame); - } else - application->getCurrentFrame()->setFid(currentId); - } - } - resetFrameRange(); - m_firstStroke = new TStroke(*stroke); - m_rangeTrack = m_track; - m_firstFrameId = currentId; - m_firstFrameRange = false; - } - - if (application && !e.isCtrlPressed()) { - if (application->getCurrentFrame()->isEditingScene()) { - application->getCurrentColumn()->setColumnIndex(m_veryFirstCol); - application->getCurrentFrame()->setFrame(m_veryFirstFrame); - } else - application->getCurrentFrame()->setFid(m_veryFirstFrameId); - } - - if (!e.isCtrlPressed()) { - resetFrameRange(); - } - } - invalidate(); - } else { - if (m_snapSelf) { - stroke->setSelfLoop(true); - m_snapSelf = false; - } - addStrokeToImage(getApplication(), vi, stroke, m_breakAngles.getValue(), - m_isFrameCreated, m_isLevelCreated); - TRectD bbox = stroke->getBBox().enlarge(2) + m_track.getModifiedRegion(); - invalidate(); // should use bbox? - } - assert(stroke); - m_track.clear(); - m_altPressed = false; - } else if (TToonzImageP ti = image) { - finishRasterBrush(pos, e.m_pressure); - } -} - -//-------------------------------------------------------------------------------------------------- - -bool BrushTool::keyDown(QKeyEvent *event) { - if (event->key() == Qt::Key_Escape) { - resetFrameRange(); - } - return false; -} - -//-------------------------------------------------------------------------------------------------- - -bool BrushTool::doFrameRangeStrokes(TFrameId firstFrameId, TStroke *firstStroke, - TFrameId lastFrameId, TStroke *lastStroke, - bool drawFirstStroke) { - TXshSimpleLevel *sl = - TTool::getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(); - TStroke *first = new TStroke(); - TStroke *last = new TStroke(); - TVectorImageP firstImage = new TVectorImage(); - TVectorImageP lastImage = new TVectorImage(); - - *first = *firstStroke; - *last = *lastStroke; - bool swapped = false; - if (firstFrameId > lastFrameId) { - tswap(firstFrameId, lastFrameId); - *first = *lastStroke; - *last = *firstStroke; - swapped = true; - } - - firstImage->addStroke(first, false); - lastImage->addStroke(last, false); - assert(firstFrameId <= lastFrameId); - - std::vector allFids; - sl->getFids(allFids); - std::vector::iterator i0 = allFids.begin(); - while (i0 != allFids.end() && *i0 < firstFrameId) i0++; - if (i0 == allFids.end()) return false; - std::vector::iterator i1 = i0; - while (i1 != allFids.end() && *i1 <= lastFrameId) i1++; - assert(i0 < i1); - std::vector fids(i0, i1); - int m = fids.size(); - assert(m > 0); - - TUndoManager::manager()->beginBlock(); - for (int i = 0; i < m; ++i) { - TFrameId fid = fids[i]; - assert(firstFrameId <= fid && fid <= lastFrameId); - - // This is an attempt to divide the tween evenly - double t = m > 1 ? (double)i / (double)(m - 1) : 0.5; - double s = t; - switch (m_frameRange.getIndex()) { - case 1: // LINEAR_WSTR - break; - case 2: // EASEIN_WSTR - s = t * t; - break; // s'(0) = 0 - case 3: // EASEOUT_WSTR - s = t * (2 - t); - break; // s'(1) = 0 - case 4: // EASEINOUT_WSTR: - s = t * t * (3 - 2 * t); - break; // s'(0) = s'(1) = 0 - } - - TTool::Application *app = TTool::getApplication(); - if (app) { - if (app->getCurrentFrame()->isEditingScene()) - app->getCurrentFrame()->setFrame(fid.getNumber() - 1); - else - app->getCurrentFrame()->setFid(fid); - } - - TVectorImageP img = sl->getFrame(fid, true); - if (t == 0) { - if (!swapped && !drawFirstStroke) { - } else - addStrokeToImage(getApplication(), img, firstImage->getStroke(0), - m_breakAngles.getValue(), m_isFrameCreated, - m_isLevelCreated, sl, fid); - } else if (t == 1) { - if (swapped && !drawFirstStroke) { - } else - addStrokeToImage(getApplication(), img, lastImage->getStroke(0), - m_breakAngles.getValue(), m_isFrameCreated, - m_isLevelCreated, sl, fid); - } else { - assert(firstImage->getStrokeCount() == 1); - assert(lastImage->getStrokeCount() == 1); - TVectorImageP vi = TInbetween(firstImage, lastImage).tween(s); - assert(vi->getStrokeCount() == 1); - addStrokeToImage(getApplication(), img, vi->getStroke(0), - m_breakAngles.getValue(), m_isFrameCreated, - m_isLevelCreated, sl, fid); - } - } - TUndoManager::manager()->endBlock(); - notifyImageChanged(); - return true; -} - -//-------------------------------------------------------------------------------------------------- - -void BrushTool::addTrackPoint(const TThickPoint &point, double pixelSize2) { - m_smoothStroke.addPoint(point); - std::vector pts; - m_smoothStroke.getSmoothPoints(pts); - for (size_t i = 0; i < pts.size(); ++i) { - m_track.add(pts[i], pixelSize2); - } -} - -//-------------------------------------------------------------------------------------------------- - -void BrushTool::flushTrackPoint() { - m_smoothStroke.endStroke(); - std::vector pts; - m_smoothStroke.getSmoothPoints(pts); - double pixelSize2 = getPixelSize() * getPixelSize(); - for (size_t i = 0; i < pts.size(); ++i) { - m_track.add(pts[i], pixelSize2); - } -} - -//--------------------------------------------------------------------------------------------------------------- -/*! - * ドラッグ中にツールが切り替わった場合に備え、onDeactivate時とMouseRelease時にと同じ終了処理を行う -*/ -void BrushTool::finishRasterBrush(const TPointD &pos, double pressureVal) { - TImageP image = getImage(true); - TToonzImageP ti = image; - if (!ti) return; - - TPointD rasCenter = ti->getRaster()->getCenterD(); - TTool::Application *app = TTool::getApplication(); - TXshLevel *level = app->getCurrentLevel()->getLevel(); - TXshSimpleLevelP simLevel = level->getSimpleLevel(); - - /*-- - * 描画中にカレントフレームが変わっても、描画開始時のFidに対してUndoを記録する - * --*/ - TFrameId frameId = - m_workingFrameId.isEmptyFrame() ? getCurrentFid() : m_workingFrameId; - - if (m_rasterTrack && (m_hardness.getValue() == 100 || m_pencil.getValue())) { - double thickness = - m_pressure.getValue() - ? computeThickness(pressureVal, m_rasThickness, m_isPath) - : m_rasThickness.getValue().second; - - /*--- ストロークの最初にMaxサイズの円が描かれてしまう不具合を防止する ---*/ - if (m_pressure.getValue() && pressureVal == 1.0) - thickness = m_rasThickness.getValue().first; - - /*-- Pencilモードでなく、Hardness=100 の場合のブラシサイズを1段階下げる --*/ - if (!m_pencil.getValue()) thickness -= 1.0; - - TRectD invalidateRect; - TThickPoint thickPoint(pos + rasCenter, thickness); - std::vector pts; - if (m_smooth.getValue() == 0) { - pts.push_back(thickPoint); - } else { - m_smoothStroke.addPoint(thickPoint); - m_smoothStroke.endStroke(); - m_smoothStroke.getSmoothPoints(pts); - } - for (size_t i = 0; i < pts.size(); ++i) { - const TThickPoint &thickPoint = pts[i]; - m_rasterTrack->add(thickPoint); - m_tileSaver->save(m_rasterTrack->getLastRect()); - m_rasterTrack->generateLastPieceOfStroke(m_pencil.getValue(), true); - - std::vector brushPoints = m_rasterTrack->getPointsSequence(); - int m = (int)brushPoints.size(); - std::vector points; - if (m == 3) { - points.push_back(brushPoints[0]); - points.push_back(brushPoints[1]); - } else { - points.push_back(brushPoints[m - 4]); - points.push_back(brushPoints[m - 3]); - points.push_back(brushPoints[m - 2]); - } - int maxThickness = m_rasThickness.getValue().second; - invalidateRect += ToolUtils::getBounds(points, maxThickness) - rasCenter; - } - invalidate(invalidateRect.enlarge(2)); - - if (m_tileSet->getTileCount() > 0) { - TUndoManager::manager()->add(new RasterBrushUndo( - m_tileSet, m_rasterTrack->getPointsSequence(), - m_rasterTrack->getStyleId(), m_rasterTrack->isSelective(), - simLevel.getPointer(), frameId, m_pencil.getValue(), m_isFrameCreated, - m_isLevelCreated, m_rasterTrack->isPaletteOrder())); - } - delete m_rasterTrack; - m_rasterTrack = 0; - } else { - double maxThickness = m_rasThickness.getValue().second; - double thickness = - (m_pressure.getValue() || m_isPath) - ? computeThickness(pressureVal, m_rasThickness, m_isPath) - : maxThickness; - TPointD rasCenter = ti->getRaster()->getCenterD(); - TRectD invalidateRect; - TThickPoint thickPoint(pos + rasCenter, thickness); - std::vector pts; - if (m_smooth.getValue() == 0) { - pts.push_back(thickPoint); - } else { - m_smoothStroke.addPoint(thickPoint); - m_smoothStroke.endStroke(); - m_smoothStroke.getSmoothPoints(pts); - } - // we need to skip the for-loop here if pts.size() == 0 or else - // (pts.size() - 1) becomes ULLONG_MAX since size_t is unsigned - if (pts.size() > 0) { - for (size_t i = 0; i < pts.size() - 1; ++i) { - TThickPoint old = m_points.back(); - - const TThickPoint &point = pts[i]; - TThickPoint mid((old + point) * 0.5, (point.thick + old.thick) * 0.5); - m_points.push_back(mid); - m_points.push_back(point); - - TRect bbox; - int m = (int)m_points.size(); - std::vector points; - if (m == 3) { - // ho appena cominciato. devo disegnare un segmento - TThickPoint pa = m_points.front(); - points.push_back(pa); - points.push_back(mid); - bbox = m_bluredBrush->getBoundFromPoints(points); - updateWorkAndBackupRasters(bbox + m_lastRect); - m_tileSaver->save(bbox); - m_bluredBrush->addArc(pa, (mid + pa) * 0.5, mid, 1, 1); - m_lastRect += bbox; - } else { - points.push_back(m_points[m - 4]); - points.push_back(old); - points.push_back(mid); - bbox = m_bluredBrush->getBoundFromPoints(points); - updateWorkAndBackupRasters(bbox + m_lastRect); - m_tileSaver->save(bbox); - m_bluredBrush->addArc(m_points[m - 4], old, mid, 1, 1); - m_lastRect += bbox; - } - - invalidateRect += - ToolUtils::getBounds(points, maxThickness) - rasCenter; - - m_bluredBrush->updateDrawing(ti->getRaster(), m_backupRas, bbox, - m_styleId, m_drawOrder.getIndex()); - m_strokeRect += bbox; - } - TThickPoint point = pts.back(); - m_points.push_back(point); - int m = m_points.size(); - std::vector points; - points.push_back(m_points[m - 3]); - points.push_back(m_points[m - 2]); - points.push_back(m_points[m - 1]); - TRect bbox = m_bluredBrush->getBoundFromPoints(points); - updateWorkAndBackupRasters(bbox); - m_tileSaver->save(bbox); - m_bluredBrush->addArc(points[0], points[1], points[2], 1, 1); - m_bluredBrush->updateDrawing(ti->getRaster(), m_backupRas, bbox, - m_styleId, m_drawOrder.getIndex()); - - invalidateRect += ToolUtils::getBounds(points, maxThickness) - rasCenter; - - m_lastRect += bbox; - m_strokeRect += bbox; - } - if (!invalidateRect.isEmpty()) invalidate(invalidateRect.enlarge(2)); - m_lastRect.empty(); - - delete m_bluredBrush; - m_bluredBrush = 0; - - if (m_tileSet->getTileCount() > 0) { - TUndoManager::manager()->add(new RasterBluredBrushUndo( - m_tileSet, m_points, m_styleId, (DrawOrder)m_drawOrder.getIndex(), - simLevel.getPointer(), frameId, m_rasThickness.getValue().second, - m_hardness.getValue() * 0.01, m_isFrameCreated, m_isLevelCreated)); - } - } - delete m_tileSaver; - - m_tileSaver = 0; - - /*-- FIdを指定して、描画中にフレームが動いても、 -   描画開始時のFidのサムネイルが更新されるようにする。--*/ - notifyImageChanged(frameId); - - m_strokeRect.empty(); - - ToolUtils::updateSaveBox(); - - /*-- 作業中のフレームをリセット --*/ - m_workingFrameId = TFrameId(); -} -//--------------------------------------------------------------------------------------------------------------- - -void BrushTool::mouseMove(const TPointD &pos, const TMouseEvent &e) { - qApp->processEvents(QEventLoop::ExcludeUserInputEvents); - - struct Locals { - BrushTool *m_this; - - void setValue(TDoublePairProperty &prop, - const TDoublePairProperty::Value &value) { - prop.setValue(value); - - m_this->onPropertyChanged(prop.getName()); - TTool::getApplication()->getCurrentTool()->notifyToolChanged(); - } - - void addMinMax(TDoublePairProperty &prop, double add) { - if (add == 0.0) return; - const TDoublePairProperty::Range &range = prop.getRange(); - - TDoublePairProperty::Value value = prop.getValue(); - value.first = tcrop(value.first + add, range.first, range.second); - value.second = tcrop(value.second + add, range.first, range.second); - - setValue(prop, value); - } - - void addMinMaxSeparate(TDoublePairProperty &prop, double min, double max) { - if (min == 0.0 && max == 0.0) return; - const TDoublePairProperty::Range &range = prop.getRange(); - - TDoublePairProperty::Value value = prop.getValue(); - value.first += min; - value.second += max; - if (value.first > value.second) value.first = value.second; - value.first = tcrop(value.first, range.first, range.second); - value.second = tcrop(value.second, range.first, range.second); - - setValue(prop, value); - } - - } locals = {this}; - - // if (e.isAltPressed() && !e.isCtrlPressed()) { - // const TPointD &diff = pos - m_mousePos; - // double add = (fabs(diff.x) > fabs(diff.y)) ? diff.x : diff.y; - - // locals.addMinMax( - // TToonzImageP(getImage(false, 1)) ? m_rasThickness : m_thickness, add); - //} else - - TPointD halfThick(m_maxThick * 0.5, m_maxThick * 0.5); - TRectD invalidateRect(m_brushPos - halfThick, m_brushPos + halfThick); - - if (e.isCtrlPressed() && e.isAltPressed() && !e.isShiftPressed()) { - const TPointD &diff = pos - m_mousePos; - double max = diff.x / 2; - double min = diff.y / 2; - - locals.addMinMaxSeparate( - (m_targetType & TTool::ToonzImage) ? m_rasThickness : m_thickness, min, - max); - - double radius = (m_targetType & TTool::ToonzImage) - ? m_rasThickness.getValue().second * 0.5 - : m_thickness.getValue().second * 0.5; - invalidateRect += TRectD(m_brushPos - TPointD(radius, radius), - m_brushPos + TPointD(radius, radius)); - - } else { - m_mousePos = pos; - m_brushPos = pos; - - if (m_targetType & TTool::Vectors) { - TPointD snapThick(6.0 * m_pixelSize, 6.0 * m_pixelSize); - // In order to clear the previous snap indicator - if (m_foundFirstSnap) - invalidateRect += - TRectD(m_firstSnapPoint - snapThick, m_firstSnapPoint + snapThick); - - m_firstSnapPoint = pos; - m_foundFirstSnap = false; - m_altPressed = e.isAltPressed() && !e.isCtrlPressed(); - checkStrokeSnapping(true, m_altPressed); - checkGuideSnapping(true, m_altPressed); - m_brushPos = m_firstSnapPoint; - // In order to draw the snap indicator - if (m_foundFirstSnap) - invalidateRect += - TRectD(m_firstSnapPoint - snapThick, m_firstSnapPoint + snapThick); - } - invalidateRect += TRectD(pos - halfThick, pos + halfThick); - } - - invalidate(invalidateRect.enlarge(2)); - - if (m_minThick == 0 && m_maxThick == 0) { - if (m_targetType & TTool::ToonzImage) { - m_minThick = m_rasThickness.getValue().first; - m_maxThick = m_rasThickness.getValue().second; - } else { - m_minThick = m_thickness.getValue().first; - m_maxThick = m_thickness.getValue().second; - } - } -} - -//------------------------------------------------------------------------------------------------------------- - -void BrushTool::checkStrokeSnapping(bool beforeMousePress, bool invertCheck) { - if (Preferences::instance()->getVectorSnappingTarget() == 1) return; - - TVectorImageP vi(getImage(false)); - bool checkSnap = m_snap.getValue(); - if (invertCheck) checkSnap = !checkSnap; - if (vi && checkSnap) { - m_dragDraw = true; - double minDistance2 = m_minDistance2; - if (beforeMousePress) - m_strokeIndex1 = -1; - else - m_strokeIndex2 = -1; - int i, strokeNumber = vi->getStrokeCount(); - TStroke *stroke; - double distance2, outW; - bool snapFound = false; - TThickPoint point1; - - for (i = 0; i < strokeNumber; i++) { - stroke = vi->getStroke(i); - if (stroke->getNearestW(m_mousePos, outW, distance2) && - distance2 < minDistance2) { - minDistance2 = distance2; - beforeMousePress ? m_strokeIndex1 = i : m_strokeIndex2 = i; - if (areAlmostEqual(outW, 0.0, 1e-3)) - beforeMousePress ? m_w1 = 0.0 : m_w2 = 0.0; - else if (areAlmostEqual(outW, 1.0, 1e-3)) - beforeMousePress ? m_w1 = 1.0 : m_w2 = 1.0; - else - beforeMousePress ? m_w1 = outW : m_w2 = outW; - - beforeMousePress ? point1 = stroke->getPoint(m_w1) - : point1 = stroke->getPoint(m_w2); - snapFound = true; - } - } - // compare to first point of current stroke - if (beforeMousePress && snapFound) { - m_firstSnapPoint = TPointD(point1.x, point1.y); - m_foundFirstSnap = true; - } else if (!beforeMousePress) { - if (!snapFound) { - TPointD tempPoint = m_track.getFirstPoint(); - double distanceFromStart = tdistance2(m_mousePos, tempPoint); - - if (distanceFromStart < m_minDistance2) { - point1 = tempPoint; - distance2 = distanceFromStart; - snapFound = true; - m_snapSelf = true; - } - } - if (snapFound) { - m_lastSnapPoint = TPointD(point1.x, point1.y); - m_foundLastSnap = true; - if (distance2 < 2.0) m_dragDraw = false; - } - } - } -} - -//------------------------------------------------------------------------------------------------------------- - -void BrushTool::checkGuideSnapping(bool beforeMousePress, bool invertCheck) { - if (Preferences::instance()->getVectorSnappingTarget() == 0) return; - bool foundSnap; - TPointD snapPoint; - beforeMousePress ? foundSnap = m_foundFirstSnap : foundSnap = m_foundLastSnap; - beforeMousePress ? snapPoint = m_firstSnapPoint : snapPoint = m_lastSnapPoint; - - bool checkSnap = m_snap.getValue(); - if (invertCheck) checkSnap = !checkSnap; - - if ((m_targetType & TTool::Vectors) && checkSnap) { - // check guide snapping - int vGuideCount = 0, hGuideCount = 0; - double guideDistance = sqrt(m_minDistance2); - TTool::Viewer *viewer = getViewer(); - if (viewer) { - vGuideCount = viewer->getVGuideCount(); - hGuideCount = viewer->getHGuideCount(); - } - double distanceToVGuide = -1.0, distanceToHGuide = -1.0; - double vGuide, hGuide; - bool useGuides = false; - if (vGuideCount) { - for (int j = 0; j < vGuideCount; j++) { - double guide = viewer->getVGuide(j); - double tempDistance = abs(guide - m_mousePos.y); - if (tempDistance < guideDistance && - (distanceToVGuide < 0 || tempDistance < distanceToVGuide)) { - distanceToVGuide = tempDistance; - vGuide = guide; - useGuides = true; - } - } - } - if (hGuideCount) { - for (int j = 0; j < hGuideCount; j++) { - double guide = viewer->getHGuide(j); - double tempDistance = abs(guide - m_mousePos.x); - if (tempDistance < guideDistance && - (distanceToHGuide < 0 || tempDistance < distanceToHGuide)) { - distanceToHGuide = tempDistance; - hGuide = guide; - useGuides = true; - } - } - } - if (useGuides && foundSnap) { - double currYDistance = abs(snapPoint.y - m_mousePos.y); - double currXDistance = abs(snapPoint.x - m_mousePos.x); - double hypotenuse = - sqrt(pow(currYDistance, 2.0) + pow(currXDistance, 2.0)); - if ((distanceToVGuide >= 0 && distanceToVGuide < hypotenuse) || - (distanceToHGuide >= 0 && distanceToHGuide < hypotenuse)) { - useGuides = true; - m_snapSelf = false; - } else - useGuides = false; - } - if (useGuides) { - assert(distanceToHGuide >= 0 || distanceToVGuide >= 0); - if (distanceToHGuide < 0 || - (distanceToVGuide <= distanceToHGuide && distanceToVGuide >= 0)) { - snapPoint.y = vGuide; - snapPoint.x = m_mousePos.x; - - } else { - snapPoint.y = m_mousePos.y; - snapPoint.x = hGuide; - } - beforeMousePress ? m_foundFirstSnap = true : m_foundLastSnap = true; - beforeMousePress ? m_firstSnapPoint = snapPoint - : m_lastSnapPoint = snapPoint; - } - } -} - -//------------------------------------------------------------------------------------------------------------- - -void BrushTool::draw() { - /*--ショートカットでのツール切り替え時に赤点が描かれるのを防止する--*/ - if (m_minThick == 0 && m_maxThick == 0 && - !Preferences::instance()->getShow0ThickLines()) - return; - - TImageP img = getImage(false, 1); - - // Draw track - tglColor(m_isPrompting ? TPixel32::Green : m_currentColor); - m_track.drawAllFragments(); - - // snapping - TVectorImageP vi = img; - if (m_targetType & TTool::Vectors) { - if (m_snap.getValue() != m_altPressed) { - m_pixelSize = getPixelSize(); - double thick = 6.0 * m_pixelSize; - if (m_foundFirstSnap) { - tglColor(TPixelD(0.1, 0.9, 0.1)); - tglDrawCircle(m_firstSnapPoint, thick); - } - - TThickPoint point2; - - if (m_foundLastSnap) { - tglColor(TPixelD(0.1, 0.9, 0.1)); - tglDrawCircle(m_lastSnapPoint, thick); - } - } - - // frame range - if (m_firstStroke) { - glColor3d(1.0, 0.0, 0.0); - m_rangeTrack.drawAllFragments(); - glColor3d(0.0, 0.6, 0.0); - TPointD firstPoint = m_rangeTrack.getFirstPoint(); - TPointD topLeftCorner = TPointD(firstPoint.x - 5, firstPoint.y - 5); - TPointD topRightCorner = TPointD(firstPoint.x + 5, firstPoint.y - 5); - TPointD bottomLeftCorner = TPointD(firstPoint.x - 5, firstPoint.y + 5); - TPointD bottomRightCorner = TPointD(firstPoint.x + 5, firstPoint.y + 5); - tglDrawSegment(topLeftCorner, bottomRightCorner); - tglDrawSegment(topRightCorner, bottomLeftCorner); - } - } - - if (getApplication()->getCurrentObject()->isSpline()) return; - - // If toggled off, don't draw brush outline - if (!Preferences::instance()->isCursorOutlineEnabled()) return; - - // Draw the brush outline - change color when the Ink / Paint check is - // activated - if ((ToonzCheck::instance()->getChecks() & ToonzCheck::eInk) || - (ToonzCheck::instance()->getChecks() & ToonzCheck::ePaint) || - (ToonzCheck::instance()->getChecks() & ToonzCheck::eInk1)) - glColor3d(0.5, 0.8, 0.8); - // normally draw in red - else - glColor3d(1.0, 0.0, 0.0); - - if (TToonzImageP ti = img) { - TRasterP ras = ti->getRaster(); - int lx = ras->getLx(); - int ly = ras->getLy(); - drawEmptyCircle(m_brushPos, tround(m_minThick), lx % 2 == 0, ly % 2 == 0, - m_pencil.getValue()); - drawEmptyCircle(m_brushPos, tround(m_maxThick), lx % 2 == 0, ly % 2 == 0, - m_pencil.getValue()); - } else if (m_targetType & TTool::ToonzImage) { - drawEmptyCircle(m_brushPos, tround(m_minThick), true, true, - m_pencil.getValue()); - drawEmptyCircle(m_brushPos, tround(m_maxThick), true, true, - m_pencil.getValue()); - } else { - tglDrawCircle(m_brushPos, 0.5 * m_minThick); - tglDrawCircle(m_brushPos, 0.5 * m_maxThick); - } -} - -//-------------------------------------------------------------------------------------------------------------- - -void BrushTool::onEnter() { - TImageP img = getImage(false); - - if (m_targetType & TTool::ToonzImage) { - m_minThick = m_rasThickness.getValue().first; - m_maxThick = m_rasThickness.getValue().second; - } else { - m_minThick = m_thickness.getValue().first; - m_maxThick = m_thickness.getValue().second; - } - - Application *app = getApplication(); - - m_styleId = app->getCurrentLevelStyleIndex(); - TColorStyle *cs = app->getCurrentLevelStyle(); - if (cs) { - TRasterStyleFx *rfx = cs->getRasterStyleFx(); - m_active = cs->isStrokeStyle() || (rfx && rfx->isInkStyle()); - m_currentColor = cs->getAverageColor(); - m_currentColor.m = 255; - } else { - m_currentColor = TPixel32::Black; - } - m_active = img; -} - -//---------------------------------------------------------------------------------------------------------- - -void BrushTool::onLeave() { - m_minThick = 0; - m_maxThick = 0; -} - -//---------------------------------------------------------------------------------------------------------- - -TPropertyGroup *BrushTool::getProperties(int idx) { - if (!m_presetsLoaded) initPresets(); - - return &m_prop[idx]; -} - -//---------------------------------------------------------------------------------------------------------- - -void BrushTool::onImageChanged() { - TToonzImageP ti = (TToonzImageP)getImage(false, 1); - if (!ti || !isEnabled()) return; - - setWorkAndBackupImages(); -} - -//---------------------------------------------------------------------------------------------------------- - -void BrushTool::setWorkAndBackupImages() { - TToonzImageP ti = (TToonzImageP)getImage(false, 1); - if (!ti) return; - - TRasterP ras = ti->getRaster(); - TDimension dim = ras->getSize(); - - double hardness = m_hardness.getValue() * 0.01; - if (hardness == 1.0 && ras->getPixelSize() == 4) { - m_workRas = TRaster32P(); - m_backupRas = TRasterCM32P(); - } else { - if (!m_workRas || m_workRas->getLx() > dim.lx || - m_workRas->getLy() > dim.ly) - m_workRas = TRaster32P(dim); - if (!m_backupRas || m_backupRas->getLx() > dim.lx || - m_backupRas->getLy() > dim.ly) - m_backupRas = TRasterCM32P(dim); - - m_strokeRect.empty(); - m_lastRect.empty(); - } -} - -//------------------------------------------------------------------ - -void BrushTool::resetFrameRange() { - m_rangeTrack.clear(); - m_firstFrameId = -1; - if (m_firstStroke) { - delete m_firstStroke; - m_firstStroke = 0; - } - m_firstFrameRange = true; -} - -//------------------------------------------------------------------ - -bool BrushTool::onPropertyChanged(std::string propertyName) { - // Set the following to true whenever a different piece of interface must - // be refreshed - done once at the end. - bool notifyTool = false; - - /*--- 変更されたPropertyに合わせて処理を分ける ---*/ - - /*--- determine which type of brush to be modified ---*/ - if (propertyName == m_thickness.getName()) { - if (m_targetType & TTool::ToonzImage) // raster - { - RasterBrushMinSize = m_rasThickness.getValue().first; - RasterBrushMaxSize = m_rasThickness.getValue().second; - - m_minThick = m_rasThickness.getValue().first; - m_maxThick = m_rasThickness.getValue().second; - } else // vector - { - VectorBrushMinSize = m_thickness.getValue().first; - VectorBrushMaxSize = m_thickness.getValue().second; - - m_minThick = m_thickness.getValue().first; - m_maxThick = m_thickness.getValue().second; - } - } else if (propertyName == m_accuracy.getName()) { - BrushAccuracy = m_accuracy.getValue(); - } else if (propertyName == m_smooth.getName()) { - BrushSmooth = m_smooth.getValue(); - } else if (propertyName == m_preset.getName()) { - loadPreset(); - notifyTool = true; - } else if (propertyName == m_drawOrder.getName()) { - BrushDrawOrder = m_drawOrder.getIndex(); - } else if (propertyName == m_breakAngles.getName()) { - BrushBreakSharpAngles = m_breakAngles.getValue(); - } else if (propertyName == m_pencil.getName()) { - RasterBrushPencilMode = m_pencil.getValue(); - } else if (propertyName == m_pressure.getName()) { - BrushPressureSensitivity = m_pressure.getValue(); - } else if (propertyName == m_capStyle.getName()) { - VectorCapStyle = m_capStyle.getIndex(); - } else if (propertyName == m_joinStyle.getName()) { - VectorJoinStyle = m_joinStyle.getIndex(); - } else if (propertyName == m_miterJoinLimit.getName()) { - VectorMiterValue = m_miterJoinLimit.getValue(); - } else if (propertyName == m_frameRange.getName()) { - int index = m_frameRange.getIndex(); - VectorBrushFrameRange = index; - if (index == 0) resetFrameRange(); - } else if (propertyName == m_snap.getName()) { - VectorBrushSnap = m_snap.getValue(); - } else if (propertyName == m_snapSensitivity.getName()) { - int index = m_snapSensitivity.getIndex(); - VectorBrushSnapSensitivity = index; - switch (index) { - case 0: - m_minDistance2 = SNAPPING_LOW; - break; - case 1: - m_minDistance2 = SNAPPING_MEDIUM; - break; - case 2: - m_minDistance2 = SNAPPING_HIGH; - break; - } - } - - if (m_targetType & TTool::Vectors) { - if (propertyName == m_joinStyle.getName()) notifyTool = true; - } - if (m_targetType & TTool::ToonzImage) { - if (propertyName == m_hardness.getName()) setWorkAndBackupImages(); - if (propertyName == m_hardness.getName() || - propertyName == m_thickness.getName()) { - m_brushPad = getBrushPad(m_rasThickness.getValue().second, - m_hardness.getValue() * 0.01); - TRectD rect(m_mousePos - TPointD(m_maxThick + 2, m_maxThick + 2), - m_mousePos + TPointD(m_maxThick + 2, m_maxThick + 2)); - invalidate(rect); - } - } - - if (propertyName != m_preset.getName() && - m_preset.getValue() != CUSTOM_WSTR) { - m_preset.setValue(CUSTOM_WSTR); - notifyTool = true; - } - - if (notifyTool) getApplication()->getCurrentTool()->notifyToolChanged(); - - return true; -} - -//------------------------------------------------------------------ - -void BrushTool::initPresets() { - if (!m_presetsLoaded) { - // If necessary, load the presets from file - m_presetsLoaded = true; - if (getTargetType() & TTool::Vectors) - m_presetsManager.load(TEnv::getConfigDir() + "brush_vector.txt"); - else - m_presetsManager.load(TEnv::getConfigDir() + "brush_toonzraster.txt"); - } - - // Rebuild the presets property entries - const std::set &presets = m_presetsManager.presets(); - - m_preset.deleteAllValues(); - m_preset.addValue(CUSTOM_WSTR); - m_preset.setItemUIName(CUSTOM_WSTR, tr("")); - - std::set::const_iterator it, end = presets.end(); - for (it = presets.begin(); it != end; ++it) m_preset.addValue(it->m_name); -} - -//---------------------------------------------------------------------------------------------------------- - -void BrushTool::loadPreset() { - const std::set &presets = m_presetsManager.presets(); - std::set::const_iterator it; - - it = presets.find(BrushData(m_preset.getValue())); - if (it == presets.end()) return; - - const BrushData &preset = *it; - - try // Don't bother with RangeErrors - { - if (getTargetType() & TTool::Vectors) { - m_thickness.setValue( - TDoublePairProperty::Value(preset.m_min, preset.m_max)); - m_accuracy.setValue(preset.m_acc, true); - m_smooth.setValue(preset.m_smooth, true); - m_breakAngles.setValue(preset.m_breakAngles); - m_pressure.setValue(preset.m_pressure); - m_capStyle.setIndex(preset.m_cap); - m_joinStyle.setIndex(preset.m_join); - m_miterJoinLimit.setValue(preset.m_miter); - } else { - m_rasThickness.setValue(TDoublePairProperty::Value( - std::max(preset.m_min, 1.0), preset.m_max)); - m_brushPad = - ToolUtils::getBrushPad(preset.m_max, preset.m_hardness * 0.01); - m_smooth.setValue(preset.m_smooth, true); - m_hardness.setValue(preset.m_hardness, true); - m_drawOrder.setIndex(preset.m_drawOrder); - m_pencil.setValue(preset.m_pencil); - m_pressure.setValue(preset.m_pressure); - } - } catch (...) { - } -} - -//------------------------------------------------------------------ - -void BrushTool::addPreset(QString name) { - // Build the preset - BrushData preset(name.toStdWString()); - - if (getTargetType() & TTool::Vectors) { - preset.m_min = m_thickness.getValue().first; - preset.m_max = m_thickness.getValue().second; - } else { - preset.m_min = m_rasThickness.getValue().first; - preset.m_max = m_rasThickness.getValue().second; - } - - preset.m_acc = m_accuracy.getValue(); - preset.m_smooth = m_smooth.getValue(); - preset.m_hardness = m_hardness.getValue(); - preset.m_drawOrder = m_drawOrder.getIndex(); - preset.m_pencil = m_pencil.getValue(); - preset.m_breakAngles = m_breakAngles.getValue(); - preset.m_pressure = m_pressure.getValue(); - preset.m_cap = m_capStyle.getIndex(); - preset.m_join = m_joinStyle.getIndex(); - preset.m_miter = m_miterJoinLimit.getValue(); - - // Pass the preset to the manager - m_presetsManager.addPreset(preset); - - // Reinitialize the associated preset enum - initPresets(); - - // Set the value to the specified one - m_preset.setValue(preset.m_name); -} - -//------------------------------------------------------------------ - -void BrushTool::removePreset() { - std::wstring name(m_preset.getValue()); - if (name == CUSTOM_WSTR) return; - - m_presetsManager.removePreset(name); - initPresets(); - - // No parameter change, and set the preset value to custom - m_preset.setValue(CUSTOM_WSTR); -} - -//------------------------------------------------------------------ -/*! Brush、PaintBrush、EraserToolがPencilModeのときにTrueを返す -*/ -bool BrushTool::isPencilModeActive() { - return getTargetType() == TTool::ToonzImage && m_pencil.getValue(); -} - -//========================================================================================================== - -// Tools instantiation - -BrushTool vectorPencil("T_Brush", TTool::Vectors | TTool::EmptyTarget); -BrushTool toonzPencil("T_Brush", TTool::ToonzImage | TTool::EmptyTarget); - -//******************************************************************************* -// Brush Data implementation -//******************************************************************************* - -BrushData::BrushData() - : m_name() - , m_min(0.0) - , m_max(0.0) - , m_acc(0.0) - , m_smooth(0.0) - , m_hardness(0.0) - , m_opacityMin(0.0) - , m_opacityMax(0.0) - , m_drawOrder(0) - , m_pencil(false) - , m_breakAngles(false) - , m_pressure(false) - , m_cap(0) - , m_join(0) - , m_miter(0) - , m_modifierSize(0.0) - , m_modifierOpacity(0.0) - , m_modifierEraser(0.0) - , m_modifierLockAlpha(0.0) {} - -//---------------------------------------------------------------------------------------------------------- - -BrushData::BrushData(const std::wstring &name) - : m_name(name) - , m_min(0.0) - , m_max(0.0) - , m_acc(0.0) - , m_smooth(0.0) - , m_hardness(0.0) - , m_opacityMin(0.0) - , m_opacityMax(0.0) - , m_drawOrder(0) - , m_pencil(false) - , m_breakAngles(false) - , m_pressure(false) - , m_cap(0) - , m_join(0) - , m_miter(0) - , m_modifierSize(0.0) - , m_modifierOpacity(0.0) - , m_modifierEraser(0.0) - , m_modifierLockAlpha(0.0) {} - -//---------------------------------------------------------------------------------------------------------- - -void BrushData::saveData(TOStream &os) { - os.openChild("Name"); - os << m_name; - os.closeChild(); - os.openChild("Thickness"); - os << m_min << m_max; - os.closeChild(); - os.openChild("Accuracy"); - os << m_acc; - os.closeChild(); - os.openChild("Smooth"); - os << m_smooth; - os.closeChild(); - os.openChild("Hardness"); - os << m_hardness; - os.closeChild(); - os.openChild("Opacity"); - os << m_opacityMin << m_opacityMax; - os.closeChild(); - os.openChild("Draw_Order"); - os << m_drawOrder; - os.closeChild(); - os.openChild("Pencil"); - os << (int)m_pencil; - os.closeChild(); - os.openChild("Break_Sharp_Angles"); - os << (int)m_breakAngles; - os.closeChild(); - os.openChild("Pressure_Sensitivity"); - os << (int)m_pressure; - os.closeChild(); - os.openChild("Cap"); - os << m_cap; - os.closeChild(); - os.openChild("Join"); - os << m_join; - os.closeChild(); - os.openChild("Miter"); - os << m_miter; - os.closeChild(); - os.openChild("Modifier_Size"); - os << m_modifierSize; - os.closeChild(); - os.openChild("Modifier_Opacity"); - os << m_modifierOpacity; - os.closeChild(); - os.openChild("Modifier_Eraser"); - os << (int)m_modifierEraser; - os.closeChild(); - os.openChild("Modifier_LockAlpha"); - os << (int)m_modifierLockAlpha; - os.closeChild(); -} - -//---------------------------------------------------------------------------------------------------------- - -void BrushData::loadData(TIStream &is) { - std::string tagName; - int val; - - while (is.matchTag(tagName)) { - if (tagName == "Name") - is >> m_name, is.matchEndTag(); - else if (tagName == "Thickness") - is >> m_min >> m_max, is.matchEndTag(); - else if (tagName == "Accuracy") - is >> m_acc, is.matchEndTag(); - else if (tagName == "Smooth") - is >> m_smooth, is.matchEndTag(); - else if (tagName == "Hardness") - is >> m_hardness, is.matchEndTag(); - else if (tagName == "Opacity") - is >> m_opacityMin >> m_opacityMax, is.matchEndTag(); - else if (tagName == "Selective" || - tagName == "Draw_Order") // "Selective" is left to keep backward - // compatibility - is >> m_drawOrder, is.matchEndTag(); - else if (tagName == "Pencil") - is >> val, m_pencil = val, is.matchEndTag(); - else if (tagName == "Break_Sharp_Angles") - is >> val, m_breakAngles = val, is.matchEndTag(); - else if (tagName == "Pressure_Sensitivity") - is >> val, m_pressure = val, is.matchEndTag(); - else if (tagName == "Cap") - is >> m_cap, is.matchEndTag(); - else if (tagName == "Join") - is >> m_join, is.matchEndTag(); - else if (tagName == "Miter") - is >> m_miter, is.matchEndTag(); - else if (tagName == "Modifier_Size") - is >> m_modifierSize, is.matchEndTag(); - else if (tagName == "Modifier_Opacity") - is >> m_modifierOpacity, is.matchEndTag(); - else if (tagName == "Modifier_Eraser") - is >> val, m_modifierEraser = val, is.matchEndTag(); - else if (tagName == "Modifier_LockAlpha") - is >> val, m_modifierLockAlpha = val, is.matchEndTag(); - else - is.skipCurrentTag(); - } -} - -//---------------------------------------------------------------------------------------------------------- - -PERSIST_IDENTIFIER(BrushData, "BrushData"); - -//******************************************************************************* -// Brush Preset Manager implementation -//******************************************************************************* - -void BrushPresetManager::load(const TFilePath &fp) { - m_fp = fp; - - std::string tagName; - BrushData data; - - TIStream is(m_fp); - try { - while (is.matchTag(tagName)) { - if (tagName == "version") { - VersionNumber version; - is >> version.first >> version.second; - - is.setVersion(version); - is.matchEndTag(); - } else if (tagName == "brushes") { - while (is.matchTag(tagName)) { - if (tagName == "brush") { - is >> data, m_presets.insert(data); - is.matchEndTag(); - } else - is.skipCurrentTag(); - } - - is.matchEndTag(); - } else - is.skipCurrentTag(); - } - } catch (...) { - } -} - -//------------------------------------------------------------------ - -void BrushPresetManager::save() { - TOStream os(m_fp); - - os.openChild("version"); - os << 1 << 19; - os.closeChild(); - - os.openChild("brushes"); - - std::set::iterator it, end = m_presets.end(); - for (it = m_presets.begin(); it != end; ++it) { - os.openChild("brush"); - os << (TPersist &)*it; - os.closeChild(); - } - - os.closeChild(); -} - -//------------------------------------------------------------------ - -void BrushPresetManager::addPreset(const BrushData &data) { - m_presets.erase(data); // Overwriting insertion - m_presets.insert(data); - save(); -} - -//------------------------------------------------------------------ - -void BrushPresetManager::removePreset(const std::wstring &name) { - m_presets.erase(BrushData(name)); - save(); -} diff --git a/toonz/sources/tnztools/brushtool.h b/toonz/sources/tnztools/brushtool.h deleted file mode 100644 index 9c71593..0000000 --- a/toonz/sources/tnztools/brushtool.h +++ /dev/null @@ -1,242 +0,0 @@ -#pragma once - -#ifndef BRUSHTOOL_H -#define BRUSHTOOL_H - -#include "tgeometry.h" -#include "tproperty.h" -#include "trasterimage.h" -#include "ttoonzimage.h" -#include "tstroke.h" -#include "toonz/strokegenerator.h" - -#include "tools/tool.h" -#include "tools/cursors.h" - -#include -#include - -//-------------------------------------------------------------- - -// Forward declarations - -class TTileSetCM32; -class TTileSaverCM32; -class RasterStrokeGenerator; -class BluredBrush; - -//-------------------------------------------------------------- - -//************************************************************************ -// Brush Data declaration -//************************************************************************ - -struct BrushData final : public TPersist { - PERSIST_DECLARATION(BrushData) - // frameRange, snapSensitivity and snap are not included - // Those options are not really a part of the brush settings, - // just the overall tool. - - std::wstring m_name; - double m_min, m_max, m_acc, m_smooth, m_hardness, m_opacityMin, m_opacityMax; - bool m_pencil, m_breakAngles, m_pressure; - int m_cap, m_join, m_miter, m_drawOrder; - double m_modifierSize, m_modifierOpacity; - bool m_modifierEraser, m_modifierLockAlpha; - - BrushData(); - BrushData(const std::wstring &name); - - bool operator<(const BrushData &other) const { return m_name < other.m_name; } - - void saveData(TOStream &os) override; - void loadData(TIStream &is) override; -}; - -//************************************************************************ -// Brush Preset Manager declaration -//************************************************************************ - -class BrushPresetManager { - TFilePath m_fp; //!< Presets file path - std::set m_presets; //!< Current presets container - -public: - BrushPresetManager() {} - - void load(const TFilePath &fp); - void save(); - - const TFilePath &path() { return m_fp; }; - const std::set &presets() const { return m_presets; } - - void addPreset(const BrushData &data); - void removePreset(const std::wstring &name); -}; - -//************************************************************************ -// Smooth Stroke declaration -// Brush stroke smoothing buffer. -//************************************************************************ -class SmoothStroke { -public: - SmoothStroke() {} - ~SmoothStroke() {} - - // begin stroke - // smooth is smooth strength, from 0 to 100 - void beginStroke(int smooth); - // add stroke point - void addPoint(const TThickPoint &point); - // end stroke - void endStroke(); - // Get generated stroke points which has been smoothed. - // Both addPoint() and endStroke() generate new smoothed points. - // This method will removed generated points - void getSmoothPoints(std::vector &smoothPoints); - // Remove all points - used for straight lines - void clearPoints(); - -private: - void generatePoints(); - -private: - int m_smooth; - int m_outputIndex; - int m_readIndex; - std::vector m_rawPoints; - std::vector m_outputPoints; -}; -//************************************************************************ -// Brush Tool declaration -//************************************************************************ - -class BrushTool final : public TTool { - Q_DECLARE_TR_FUNCTIONS(BrushTool) - -public: - BrushTool(std::string name, int targetType); - - ToolType getToolType() const override { return TTool::LevelWriteTool; } - - ToolOptionsBox *createOptionsBox() override; - - void updateTranslation() override; - - void onActivate() override; - void onDeactivate() override; - - bool preLeftButtonDown() override; - void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override; - void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override; - void leftButtonUp(const TPointD &pos, const TMouseEvent &e) override; - void mouseMove(const TPointD &pos, const TMouseEvent &e) override; - bool keyDown(QKeyEvent *event) override; - - void draw() override; - - void onEnter() override; - void onLeave() override; - - int getCursorId() const override { return ToolCursor::PenCursor; } - - TPropertyGroup *getProperties(int targetType) override; - bool onPropertyChanged(std::string propertyName) override; - void resetFrameRange(); - void onImageChanged() override; - void setWorkAndBackupImages(); - void updateWorkAndBackupRasters(const TRect &rect); - - void initPresets(); - void loadPreset(); - void addPreset(QString name); - void removePreset(); - - void finishRasterBrush(const TPointD &pos, double pressureVal); - // return true if the pencil mode is active in the Brush / PaintBrush / Eraser - // Tools. - bool isPencilModeActive() override; - - void addTrackPoint(const TThickPoint &point, double pixelSize2); - void flushTrackPoint(); - bool doFrameRangeStrokes(TFrameId firstFrameId, TStroke *firstStroke, - TFrameId lastFrameId, TStroke *lastStroke, - bool drawFirstStroke = true); - void checkGuideSnapping(bool beforeMousePress, bool invertCheck); - void checkStrokeSnapping(bool beforeMousePress, bool invertCheck); - -protected: - TPropertyGroup m_prop[2]; - - TDoublePairProperty m_thickness; - TDoublePairProperty m_rasThickness; - TDoubleProperty m_accuracy; - TDoubleProperty m_smooth; - TDoubleProperty m_hardness; - TEnumProperty m_preset; - TEnumProperty m_drawOrder; - TBoolProperty m_breakAngles; - TBoolProperty m_pencil; - TBoolProperty m_pressure; - TBoolProperty m_snap; - TEnumProperty m_frameRange; - TEnumProperty m_snapSensitivity; - TEnumProperty m_capStyle; - TEnumProperty m_joinStyle; - TIntProperty m_miterJoinLimit; - - StrokeGenerator m_track; - StrokeGenerator m_rangeTrack; - RasterStrokeGenerator *m_rasterTrack; - TStroke *m_firstStroke; - TTileSetCM32 *m_tileSet; - TTileSaverCM32 *m_tileSaver; - TFrameId m_firstFrameId, m_veryFirstFrameId; - TPixel32 m_currentColor; - int m_styleId; - double m_minThick, m_maxThick; - - // for snapping and framerange - int m_strokeIndex1, m_strokeIndex2, m_col, m_firstFrame, m_veryFirstFrame, - m_veryFirstCol, m_targetType; - double m_w1, m_w2, m_pixelSize, m_currThickness, m_minDistance2; - bool m_foundFirstSnap = false, m_foundLastSnap = false, m_dragDraw = true, - m_altPressed = false, m_snapSelf = false; - TRectD m_modifiedRegion; - TPointD m_dpiScale, - m_mousePos, //!< Current mouse position, in world coordinates. - m_brushPos, //!< World position the brush will be painted at. - m_firstSnapPoint, m_lastSnapPoint; - - BluredBrush *m_bluredBrush; - QRadialGradient m_brushPad; - - TRasterCM32P m_backupRas; - TRaster32P m_workRas; - - std::vector m_points; - TRect m_strokeRect, m_lastRect; - - SmoothStroke m_smoothStroke; - - BrushPresetManager - m_presetsManager; //!< Manager for presets of this tool instance - - bool m_active, m_enabled, - m_isPrompting, //!< Whether the tool is prompting for spline - //! substitution. - m_firstTime, m_isPath, m_presetsLoaded, m_firstFrameRange; - - /*--- -作業中のFrameIdをクリック時に保存し、マウスリリース時(Undoの登録時)に別のフレームに -移動していたときの不具合を修正する。---*/ - TFrameId m_workingFrameId; - -protected: - static void drawLine(const TPointD &point, const TPointD ¢re, - bool horizontal, bool isDecimal); - static void drawEmptyCircle(TPointD point, int thick, bool isLxEven, - bool isLyEven, bool isPencil); -}; - -#endif // BRUSHTOOL_H diff --git a/toonz/sources/tnztools/controlpointeditortool.cpp b/toonz/sources/tnztools/controlpointeditortool.cpp index fb58527..3b20917 100644 --- a/toonz/sources/tnztools/controlpointeditortool.cpp +++ b/toonz/sources/tnztools/controlpointeditortool.cpp @@ -484,9 +484,9 @@ void ControlPointEditorTool::leftButtonDown(const TPointD &pos, // ho cliccato lontano da ogni altra curva m_selectingRect = TRectD(m_pos.x, m_pos.y, m_pos.x + 1, m_pos.y + 1); if (m_selectingRect.x0 > m_selectingRect.x1) - tswap(m_selectingRect.x1, m_selectingRect.x0); + std::swap(m_selectingRect.x1, m_selectingRect.x0); if (m_selectingRect.y0 > m_selectingRect.y1) - tswap(m_selectingRect.y1, m_selectingRect.y0); + std::swap(m_selectingRect.y1, m_selectingRect.y0); m_action = RECT_SELECTION; } m_selection.selectNone(); @@ -560,7 +560,7 @@ void ControlPointEditorTool::leftButtonDown(const TPointD &pos, : precPointIndex + 1; if (precPointIndex > -1 && nextPointIndex > -1) { if (precPointIndex > nextPointIndex) - tswap(precPointIndex, nextPointIndex); + std::swap(precPointIndex, nextPointIndex); m_moveSegmentLimitation.first = precPointIndex; m_moveSegmentLimitation.second = nextPointIndex; } @@ -691,9 +691,9 @@ void ControlPointEditorTool::leftButtonDrag(const TPointD &pos, m_selectingRect.x1 = pos.x; m_selectingRect.y1 = pos.y; if (m_selectingRect.x0 > m_selectingRect.x1) - tswap(m_selectingRect.x1, m_selectingRect.x0); + std::swap(m_selectingRect.x1, m_selectingRect.x0); if (m_selectingRect.y0 > m_selectingRect.y1) - tswap(m_selectingRect.y1, m_selectingRect.y0); + std::swap(m_selectingRect.y1, m_selectingRect.y0); int i; m_selection.selectNone(); for (i = 0; i < cpCount; i++) diff --git a/toonz/sources/tnztools/controlpointselection.cpp b/toonz/sources/tnztools/controlpointselection.cpp index b6a9266..cb67c7f 100644 --- a/toonz/sources/tnztools/controlpointselection.cpp +++ b/toonz/sources/tnztools/controlpointselection.cpp @@ -736,7 +736,7 @@ int ControlPointEditorStroke::addControlPoint(const TPointD &pos) { if (pointIndex > precCp.m_pointIndex + 2) { // nel caso in cui sono nel secondo chunk scambio i punti a0 = a4; - tswap(a1, a3); + std::swap(a1, a3); isInFirstChunk = false; } @@ -850,7 +850,7 @@ void ControlPointEditorStroke::moveSegment(int beforeIndex, int nextIndex, int cpCount = getControlPointCount(); // Verifiche per il caso in cui lo stroke e' selfLoop if (isSelfLoop() && beforeIndex == 0 && nextIndex == cpCount - 1) - tswap(beforeIndex, nextIndex); + std::swap(beforeIndex, nextIndex); int beforePointIndex = m_controlPoints[beforeIndex].m_pointIndex; int nextPointIndex = (isSelfLoop() && nextIndex == 0) diff --git a/toonz/sources/tnztools/cuttertool.cpp b/toonz/sources/tnztools/cuttertool.cpp index 9e93f7d..677324f 100644 --- a/toonz/sources/tnztools/cuttertool.cpp +++ b/toonz/sources/tnztools/cuttertool.cpp @@ -8,7 +8,6 @@ #include "toonz/tcolumnhandle.h" #include "toonz/txshlevelhandle.h" #include "tools/strokeselection.h" -#include "tools/tool.h" #include "tmathutil.h" #include "tstroke.h" diff --git a/toonz/sources/tnztools/edittoolgadgets.cpp b/toonz/sources/tnztools/edittoolgadgets.cpp index 1effcb5..8dc24e5 100644 --- a/toonz/sources/tnztools/edittoolgadgets.cpp +++ b/toonz/sources/tnztools/edittoolgadgets.cpp @@ -13,7 +13,6 @@ #include "toonz/tcolumnfx.h" #include "tdoubleparam.h" #include "tparamset.h" -#include "toonz/stage.h" #include "tundo.h" #include "tparamuiconcept.h" diff --git a/toonz/sources/tnztools/filltool.cpp b/toonz/sources/tnztools/filltool.cpp index 16facea..15c85a8 100644 --- a/toonz/sources/tnztools/filltool.cpp +++ b/toonz/sources/tnztools/filltool.cpp @@ -1024,7 +1024,7 @@ void SequencePainter::processSequence(TXshSimpleLevel *sl, TFrameId firstFid, bool backward = false; if (firstFid > lastFid) { - tswap(firstFid, lastFid); + std::swap(firstFid, lastFid); backward = true; } assert(firstFid <= lastFid); @@ -1421,9 +1421,9 @@ void AreaFillTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) { m_selecting = false; if (m_type == RECT) { if (m_selectingRect.x0 > m_selectingRect.x1) - tswap(m_selectingRect.x0, m_selectingRect.x1); + std::swap(m_selectingRect.x0, m_selectingRect.x1); if (m_selectingRect.y0 > m_selectingRect.y1) - tswap(m_selectingRect.y0, m_selectingRect.y1); + std::swap(m_selectingRect.y0, m_selectingRect.y1); if (m_frameRange) { if (m_firstFrameSelected) { diff --git a/toonz/sources/tnztools/fingertool.cpp b/toonz/sources/tnztools/fingertool.cpp index b38a480..f3871d4 100644 --- a/toonz/sources/tnztools/fingertool.cpp +++ b/toonz/sources/tnztools/fingertool.cpp @@ -35,7 +35,6 @@ #include "toonz/txshlevelhandle.h" #include "toonz/tframehandle.h" #include "tools/toolhandle.h" -#include "tools/toolutils.h" // For Qt translation support #include diff --git a/toonz/sources/tnztools/fullcolorbrushtool.cpp b/toonz/sources/tnztools/fullcolorbrushtool.cpp index 08fb0aa..fde2213 100644 --- a/toonz/sources/tnztools/fullcolorbrushtool.cpp +++ b/toonz/sources/tnztools/fullcolorbrushtool.cpp @@ -350,6 +350,8 @@ void FullColorBrushTool::leftButtonDrag(const TPointD &pos, TRasterImageP ri = (TRasterImageP)getImage(true); if (!ri) return; + if (!m_toonz_brush) return; + TRasterP ras = ri->getRaster(); TPointD rasCenter = ras->getCenterD(); TPointD point(pos + rasCenter); @@ -379,6 +381,8 @@ void FullColorBrushTool::leftButtonUp(const TPointD &pos, TRasterImageP ri = (TRasterImageP)getImage(true); if (!ri) return; + if (!m_toonz_brush) return; + TRasterP ras = ri->getRaster(); TPointD rasCenter = ras->getCenterD(); TPointD point(pos + rasCenter); diff --git a/toonz/sources/tnztools/fullcolorbrushtool.h b/toonz/sources/tnztools/fullcolorbrushtool.h index b4039af..9ac9320 100644 --- a/toonz/sources/tnztools/fullcolorbrushtool.h +++ b/toonz/sources/tnztools/fullcolorbrushtool.h @@ -5,7 +5,7 @@ #include -#include "brushtool.h" +#include "toonzrasterbrushtool.h" #include "mypainttoonzbrush.h" #include "toonz/mypaintbrushstyle.h" #include @@ -18,7 +18,9 @@ class TTileSetFullColor; class TTileSaverFullColor; class MyPaintToonzBrush; class FullColorBrushToolNotifier; -namespace mypaint { class Brush; } +namespace mypaint { +class Brush; +} //============================================================== @@ -77,7 +79,7 @@ public: void onCanvasSizeChanged(); void onColorStyleChanged(); - TMyPaintBrushStyle* getBrushStyle(); + TMyPaintBrushStyle *getBrushStyle(); protected: TPropertyGroup m_prop; @@ -97,7 +99,7 @@ protected: int m_minCursorThick, m_maxCursorThick; TPointD m_mousePos, //!< Current mouse position, in world coordinates. - m_brushPos; //!< World position the brush will be painted at. + m_brushPos; //!< World position the brush will be painted at. TRasterP m_backUpRas; TRaster32P m_workRaster; diff --git a/toonz/sources/tnztools/fullcolorerasertool.cpp b/toonz/sources/tnztools/fullcolorerasertool.cpp index 4ff46de..5b6722e 100644 --- a/toonz/sources/tnztools/fullcolorerasertool.cpp +++ b/toonz/sources/tnztools/fullcolorerasertool.cpp @@ -5,7 +5,6 @@ #include "tools/cursors.h" #include "tools/toolcommandids.h" #include "tools/toolutils.h" -#include "tools/toolutils.h" #include "tools/toolhandle.h" #include "historytypes.h" @@ -527,6 +526,8 @@ void FullColorEraserTool::leftButtonDown(const TPointD &pos, void FullColorEraserTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { + if (!m_mousePressed) return; + m_brushPos = m_mousePos = pos; m_mouseEvent = e; double pixelSize2 = getPixelSize() * getPixelSize(); @@ -580,15 +581,15 @@ void FullColorEraserTool::leftButtonDrag(const TPointD &pos, if (m_eraseType.getValue() == RECTERASE) { assert(m_selecting); TRectD oldRect = m_selectingRect; - if (oldRect.x0 > oldRect.x1) tswap(oldRect.x1, oldRect.x0); - if (oldRect.y0 > oldRect.y1) tswap(oldRect.y1, oldRect.y0); + if (oldRect.x0 > oldRect.x1) std::swap(oldRect.x1, oldRect.x0); + if (oldRect.y0 > oldRect.y1) std::swap(oldRect.y1, oldRect.y0); m_selectingRect.x1 = pos.x; m_selectingRect.y1 = pos.y; TRectD invalidateRect(m_selectingRect); if (invalidateRect.x0 > invalidateRect.x1) - tswap(invalidateRect.x1, invalidateRect.x0); + std::swap(invalidateRect.x1, invalidateRect.x0); if (invalidateRect.y0 > invalidateRect.y1) - tswap(invalidateRect.y1, invalidateRect.y0); + std::swap(invalidateRect.y1, invalidateRect.y0); invalidateRect += oldRect; invalidate(invalidateRect.enlarge(2)); } @@ -647,9 +648,9 @@ void FullColorEraserTool::leftButtonUp(const TPointD &pos, notifyImageChanged(); } else if (m_eraseType.getValue() == RECTERASE) { if (m_selectingRect.x0 > m_selectingRect.x1) - tswap(m_selectingRect.x1, m_selectingRect.x0); + std::swap(m_selectingRect.x1, m_selectingRect.x0); if (m_selectingRect.y0 > m_selectingRect.y1) - tswap(m_selectingRect.y1, m_selectingRect.y0); + std::swap(m_selectingRect.y1, m_selectingRect.y0); if (m_multi.getValue()) { TTool::Application *app = TTool::getApplication(); @@ -1042,7 +1043,7 @@ void FullColorEraserTool::multiUpdate(const TRectD firstRect, TFrameId firstFid = m_firstFrameId; TFrameId lastFid = getCurrentFid(); if (firstFid > lastFid) { - tswap(firstFid, lastFid); + std::swap(firstFid, lastFid); backward = true; } assert(firstFid <= lastFid); @@ -1114,7 +1115,7 @@ void FullColorEraserTool::multiAreaEraser(TFrameId &firstFid, TFrameId &lastFid, bool backward = false; if (firstFid > lastFid) { - tswap(firstFid, lastFid); + std::swap(firstFid, lastFid); backward = true; } assert(firstFid <= lastFid); diff --git a/toonz/sources/tnztools/irontool.cpp b/toonz/sources/tnztools/irontool.cpp index f583eae..fe65726 100644 --- a/toonz/sources/tnztools/irontool.cpp +++ b/toonz/sources/tnztools/irontool.cpp @@ -168,7 +168,7 @@ public: if (!direction) { draggedStrokeLen = totalStrokeLen - draggedStrokeLen; - tswap(v0, v1); + std::swap(v0, v1); } // se la lunghezza della parte di stroke tra i due punti di inizio e fine diff --git a/toonz/sources/tnztools/mypainttoonzbrush.cpp b/toonz/sources/tnztools/mypainttoonzbrush.cpp index f6e722b..c3670dc 100644 --- a/toonz/sources/tnztools/mypainttoonzbrush.cpp +++ b/toonz/sources/tnztools/mypainttoonzbrush.cpp @@ -8,6 +8,35 @@ #include +namespace { +void putOnRasterCM(const TRasterCM32P &out, const TRaster32P &in, int styleId) { + if (!out.getPointer() || !in.getPointer()) return; + assert(out->getSize() == in->getSize()); + int x, y; + for (y = 0; y < out->getLy(); y++) { + for (x = 0; x < out->getLx(); x++) { +#ifdef _DEBUG + assert(x >= 0 && x < in->getLx()); + assert(y >= 0 && y < in->getLy()); + assert(x >= 0 && x < out->getLx()); + assert(y >= 0 && y < out->getLy()); +#endif + TPixel32 *inPix = &in->pixels(y)[x]; + if (inPix->m == 0) continue; + TPixelCM32 *outPix = &out->pixels(y)[x]; + bool sameStyleId = styleId == outPix->getInk(); + // line with the same style : multiply tones + // line with different style : pick darker tone + int tone = sameStyleId ? outPix->getTone() * (255 - inPix->m) / 255 + : std::min(255 - inPix->m, outPix->getTone()); + int ink = !sameStyleId && outPix->getTone() < 255 - inPix->m + ? outPix->getInk() + : styleId; + *outPix = TPixelCM32(ink, outPix->getPaint(), tone); + } + } +} +} // namespace //======================================================= // @@ -15,19 +44,15 @@ // //======================================================= -class Raster32PMyPaintSurface::Internal: - public mypaint::helpers::SurfaceCustom -{ +class Raster32PMyPaintSurface::Internal + : public mypaint::helpers::SurfaceCustom { public: typedef SurfaceCustom Parent; - Internal(Raster32PMyPaintSurface &owner): - SurfaceCustom( owner.m_ras->pixels(), - owner.m_ras->getLx(), - owner.m_ras->getLy(), - owner.m_ras->getPixelSize(), - owner.m_ras->getRowSize(), - &owner ) - { } + Internal(Raster32PMyPaintSurface &owner) + : SurfaceCustom(owner.m_ras->pixels(), owner.m_ras->getLx(), + owner.m_ras->getLy(), owner.m_ras->getPixelSize(), + owner.m_ras->getRowSize(), &owner) {} }; //======================================================= @@ -36,39 +61,38 @@ public: // //======================================================= -Raster32PMyPaintSurface::Raster32PMyPaintSurface(const TRaster32P &ras): - m_ras(ras), - controller(), - internal() -{ +Raster32PMyPaintSurface::Raster32PMyPaintSurface(const TRaster32P &ras) + : m_ras(ras), controller(), internal() { assert(ras); internal = new Internal(*this); } -Raster32PMyPaintSurface::Raster32PMyPaintSurface(const TRaster32P &ras, RasterController &controller): - m_ras(ras), - controller(&controller), - internal() -{ +Raster32PMyPaintSurface::Raster32PMyPaintSurface(const TRaster32P &ras, + RasterController &controller) + : m_ras(ras), controller(&controller), internal() { assert(ras); internal = new Internal(*this); } -Raster32PMyPaintSurface::~Raster32PMyPaintSurface() - { delete internal; } +Raster32PMyPaintSurface::~Raster32PMyPaintSurface() { delete internal; } bool Raster32PMyPaintSurface::getColor(float x, float y, float radius, - float &colorR, float &colorG, float &colorB, float &colorA) -{ return internal->getColor(x, y, radius, colorR, colorG, colorB, colorA); } + float &colorR, float &colorG, + float &colorB, float &colorA) { + return internal->getColor(x, y, radius, colorR, colorG, colorB, colorA); +} -bool Raster32PMyPaintSurface::drawDab(const mypaint::Dab &dab) - { return internal->drawDab(dab); } +bool Raster32PMyPaintSurface::drawDab(const mypaint::Dab &dab) { + return internal->drawDab(dab); +} -bool Raster32PMyPaintSurface::getAntialiasing() const - { return internal->antialiasing; } +bool Raster32PMyPaintSurface::getAntialiasing() const { + return internal->antialiasing; +} -void Raster32PMyPaintSurface::setAntialiasing(bool value) - { internal->antialiasing = value; } +void Raster32PMyPaintSurface::setAntialiasing(bool value) { + internal->antialiasing = value; +} //======================================================= // @@ -76,20 +100,22 @@ void Raster32PMyPaintSurface::setAntialiasing(bool value) // //======================================================= -MyPaintToonzBrush::MyPaintToonzBrush(const TRaster32P &ras, RasterController &controller, const mypaint::Brush &brush): - m_ras(ras), - m_mypaintSurface(m_ras, controller), - brush(brush), - reset(true) -{ +MyPaintToonzBrush::MyPaintToonzBrush(const TRaster32P &ras, + RasterController &controller, + const mypaint::Brush &brush) + : m_ras(ras) + , m_mypaintSurface(m_ras, controller) + , brush(brush) + , reset(true) { // read brush antialiasing settings float aa = this->brush.getBaseValue(MYPAINT_BRUSH_SETTING_ANTI_ALIASING); m_mypaintSurface.setAntialiasing(aa > 0.5f); // reset brush antialiasing to zero to avoid radius and hardness correction this->brush.setBaseValue(MYPAINT_BRUSH_SETTING_ANTI_ALIASING, 0.f); - for(int i = 0; i < MYPAINT_BRUSH_INPUTS_COUNT; ++i) - this->brush.setMappingN(MYPAINT_BRUSH_SETTING_ANTI_ALIASING, (MyPaintBrushInput)i, 0); + for (int i = 0; i < MYPAINT_BRUSH_INPUTS_COUNT; ++i) + this->brush.setMappingN(MYPAINT_BRUSH_SETTING_ANTI_ALIASING, + (MyPaintBrushInput)i, 0); } void MyPaintToonzBrush::beginStroke() { @@ -105,13 +131,14 @@ void MyPaintToonzBrush::endStroke() { } } -void MyPaintToonzBrush::strokeTo(const TPointD &point, double pressure, double dtime) { +void MyPaintToonzBrush::strokeTo(const TPointD &point, double pressure, + double dtime) { Params next(point.x, point.y, pressure, 0.0); if (reset) { - current = next; + current = next; previous = current; - reset = false; + reset = false; // we need to jump to initial point (heuristic) brush.setState(MYPAINT_BRUSH_STATE_X, current.x); brush.setState(MYPAINT_BRUSH_STATE_Y, current.y); @@ -123,31 +150,33 @@ void MyPaintToonzBrush::strokeTo(const TPointD &point, double pressure, double d } // accuracy - const double threshold = 1.0; - const double thresholdSqr = threshold*threshold; - const int maxLevel = 16; + const double threshold = 1.0; + const double thresholdSqr = threshold * threshold; + const int maxLevel = 16; // set initial segment - Segment stack[maxLevel+1]; + Segment stack[maxLevel + 1]; Params p0; - Segment *segment = stack; + Segment *segment = stack; Segment *maxSegment = segment + maxLevel; p0.setMedian(previous, current); segment->p1 = current; segment->p2.setMedian(current, next); // process - while(true) { + while (true) { double dx = segment->p2.x - p0.x; double dy = segment->p2.y - p0.y; - if (dx*dx + dy*dy > thresholdSqr && segment != maxSegment) { + if (dx * dx + dy * dy > thresholdSqr && segment != maxSegment) { Segment *sub = segment + 1; sub->p1.setMedian(p0, segment->p1); segment->p1.setMedian(segment->p1, segment->p2); sub->p2.setMedian(sub->p1, segment->p1); segment = sub; } else { - brush.strokeTo(m_mypaintSurface, segment->p2.x, segment->p2.y, segment->p2.pressure, 0.f, 0.f, segment->p2.time - p0.time); + brush.strokeTo(m_mypaintSurface, segment->p2.x, segment->p2.y, + segment->p2.pressure, 0.f, 0.f, + segment->p2.time - p0.time); if (segment == stack) break; p0 = segment->p2; --segment; @@ -160,6 +189,21 @@ void MyPaintToonzBrush::strokeTo(const TPointD &point, double pressure, double d // shift time previous.time = 0.0; - current.time = dtime; + current.time = dtime; } +//---------------------------------------------------------------------------------- + +void MyPaintToonzBrush::updateDrawing(const TRasterCM32P rasCM, + const TRasterCM32P rasBackupCM, + const TRect &bbox, int styleId) const { + if (!rasCM) return; + + TRect rasRect = rasCM->getBounds(); + TRect targetRect = bbox * rasRect; + if (targetRect.isEmpty()) return; + + rasCM->copy(rasBackupCM->extract(targetRect), targetRect.getP00()); + putOnRasterCM(rasCM->extract(targetRect), m_ras->extract(targetRect), + styleId); +} \ No newline at end of file diff --git a/toonz/sources/tnztools/mypainttoonzbrush.h b/toonz/sources/tnztools/mypainttoonzbrush.h index 898fe2c..352afa5 100644 --- a/toonz/sources/tnztools/mypainttoonzbrush.h +++ b/toonz/sources/tnztools/mypainttoonzbrush.h @@ -10,10 +10,9 @@ #include #include - class RasterController { public: - virtual ~RasterController() { } + virtual ~RasterController() {} virtual bool askRead(const TRect &rect) { return true; } virtual bool askWrite(const TRect &rect) { return true; } }; @@ -24,7 +23,7 @@ public: // //======================================================= -class Raster32PMyPaintSurface: public mypaint::Surface { +class Raster32PMyPaintSurface : public mypaint::Surface { private: class Internal; @@ -32,39 +31,50 @@ private: RasterController *controller; Internal *internal; - inline static void readPixel(const void *pixelPtr, float &colorR, float &colorG, float &colorB, float &colorA) { - const TPixel32 &pixel = *(const TPixel32*)pixelPtr; - colorR = (float)pixel.r/(float)TPixel32::maxChannelValue; - colorG = (float)pixel.g/(float)TPixel32::maxChannelValue; - colorB = (float)pixel.b/(float)TPixel32::maxChannelValue; - colorA = (float)pixel.m/(float)TPixel32::maxChannelValue; + inline static void readPixel(const void *pixelPtr, float &colorR, + float &colorG, float &colorB, float &colorA) { + const TPixel32 &pixel = *(const TPixel32 *)pixelPtr; + colorR = (float)pixel.r / (float)TPixel32::maxChannelValue; + colorG = (float)pixel.g / (float)TPixel32::maxChannelValue; + colorB = (float)pixel.b / (float)TPixel32::maxChannelValue; + colorA = (float)pixel.m / (float)TPixel32::maxChannelValue; } - inline static void writePixel(void *pixelPtr, float colorR, float colorG, float colorB, float colorA) { - TPixel32 &pixel = *(TPixel32*)pixelPtr; + inline static void writePixel(void *pixelPtr, float colorR, float colorG, + float colorB, float colorA) { + TPixel32 &pixel = *(TPixel32 *)pixelPtr; pixel.r = (TPixel32::Channel)roundf(colorR * TPixel32::maxChannelValue); pixel.g = (TPixel32::Channel)roundf(colorG * TPixel32::maxChannelValue); pixel.b = (TPixel32::Channel)roundf(colorB * TPixel32::maxChannelValue); pixel.m = (TPixel32::Channel)roundf(colorA * TPixel32::maxChannelValue); } - inline static bool askRead(void *surfaceController, const void* /* surfacePointer */, int x0, int y0, int x1, int y1) { - Raster32PMyPaintSurface &owner = *((Raster32PMyPaintSurface*)surfaceController); - return !owner.controller || owner.controller->askRead(TRect(x0, y0, x1, y1)); + inline static bool askRead(void *surfaceController, + const void * /* surfacePointer */, int x0, int y0, + int x1, int y1) { + Raster32PMyPaintSurface &owner = + *((Raster32PMyPaintSurface *)surfaceController); + return !owner.controller || + owner.controller->askRead(TRect(x0, y0, x1, y1)); } - inline static bool askWrite(void *surfaceController, const void* /* surfacePointer */, int x0, int y0, int x1, int y1) { - Raster32PMyPaintSurface &owner = *((Raster32PMyPaintSurface*)surfaceController); - return !owner.controller || owner.controller->askWrite(TRect(x0, y0, x1, y1)); + inline static bool askWrite(void *surfaceController, + const void * /* surfacePointer */, int x0, int y0, + int x1, int y1) { + Raster32PMyPaintSurface &owner = + *((Raster32PMyPaintSurface *)surfaceController); + return !owner.controller || + owner.controller->askWrite(TRect(x0, y0, x1, y1)); } public: explicit Raster32PMyPaintSurface(const TRaster32P &ras); - explicit Raster32PMyPaintSurface(const TRaster32P &ras, RasterController &controller); + explicit Raster32PMyPaintSurface(const TRaster32P &ras, + RasterController &controller); ~Raster32PMyPaintSurface(); - bool getColor(float x, float y, float radius, - float &colorR, float &colorG, float &colorB, float &colorA) override; + bool getColor(float x, float y, float radius, float &colorR, float &colorG, + float &colorB, float &colorA) override; bool drawDab(const mypaint::Dab &dab) override; @@ -82,16 +92,21 @@ class MyPaintToonzBrush { private: struct Params { union { - struct { double x, y, pressure, time; }; - struct { double values[4]; }; + struct { + double x, y, pressure, time; + }; + struct { + double values[4]; + }; }; - inline explicit Params(double x = 0.0, double y = 0.0, double pressure = 0.0, double time = 0.0): - x(x), y(y), pressure(pressure), time(time) { } + inline explicit Params(double x = 0.0, double y = 0.0, + double pressure = 0.0, double time = 0.0) + : x(x), y(y), pressure(pressure), time(time) {} inline void setMedian(Params &a, Params &b) { - for(int i = 0; i < (int)sizeof(values)/sizeof(values[0]); ++i) - values[i] = 0.5*(a.values[i] + b.values[i]); + for (int i = 0; i < (int)sizeof(values) / sizeof(values[0]); ++i) + values[i] = 0.5 * (a.values[i] + b.values[i]); } }; @@ -107,10 +122,15 @@ private: Params previous, current; public: - MyPaintToonzBrush(const TRaster32P &ras, RasterController &controller, const mypaint::Brush &brush); + MyPaintToonzBrush(const TRaster32P &ras, RasterController &controller, + const mypaint::Brush &brush); void beginStroke(); void endStroke(); void strokeTo(const TPointD &p, double pressure, double dtime); + + // colormapped + void updateDrawing(const TRasterCM32P rasCM, const TRasterCM32P rasBackupCM, + const TRect &bbox, int styleId) const; }; #endif // T_BLUREDBRUSH diff --git a/toonz/sources/tnztools/paintbrushtool.cpp b/toonz/sources/tnztools/paintbrushtool.cpp index 3c2cbe9..ebf5ca9 100644 --- a/toonz/sources/tnztools/paintbrushtool.cpp +++ b/toonz/sources/tnztools/paintbrushtool.cpp @@ -34,7 +34,6 @@ #include "toonz/txshlevelhandle.h" #include "toonz/tframehandle.h" #include "tools/toolhandle.h" -#include "tools/toolutils.h" // For Qt translation support #include diff --git a/toonz/sources/tnztools/pinchtool.cpp b/toonz/sources/tnztools/pinchtool.cpp index e164da8..004db42 100644 --- a/toonz/sources/tnztools/pinchtool.cpp +++ b/toonz/sources/tnztools/pinchtool.cpp @@ -45,7 +45,6 @@ #include "ext/Selector.h" #include "ext/CornerDeformation.h" #include "ext/StraightCornerDeformation.h" -#include "ext/StrokeDeformation.h" #include #include diff --git a/toonz/sources/tnztools/plastictool.cpp b/toonz/sources/tnztools/plastictool.cpp index 626073f..364bb17 100644 --- a/toonz/sources/tnztools/plastictool.cpp +++ b/toonz/sources/tnztools/plastictool.cpp @@ -997,9 +997,13 @@ void PlasticTool::onDeactivate() { assert(ret); Viewer *viewer = getViewer(); - if (viewer) + if (viewer) { viewer->visualSettings().m_plasticVisualSettings = PlasticVisualSettings(); - + // Only the mesh visibility is not reset in order to enable to keep the mesh + // hidden while using other tools + viewer->visualSettings().m_plasticVisualSettings.m_drawMeshesWireframe = + m_pvs.m_drawMeshesWireframe; + } m_sd = PlasticSkeletonDeformationP(); } diff --git a/toonz/sources/tnztools/plastictool_meshedit.cpp b/toonz/sources/tnztools/plastictool_meshedit.cpp index 52752cc..22deeb1 100644 --- a/toonz/sources/tnztools/plastictool_meshedit.cpp +++ b/toonz/sources/tnztools/plastictool_meshedit.cpp @@ -13,8 +13,6 @@ #include "tcg/tcg_point_ops.h" #include "tcg/tcg_iterator_ops.h" #include "tcg/tcg_function_types.h" -#include "tcg/tcg_deleter_types.h" -#include "tcg/tcg_unique_ptr.h" // boost includes #include @@ -515,8 +513,7 @@ void splitUnconnectedMesh(TMeshImage &mi, int meshIdx) { static void buildConnectedComponent(const TTextureMesh &mesh, boost::unordered_set &vertexes) { // Prepare BFS algorithm - tcg::unique_ptr colorMapP( - (UCHAR *)calloc(mesh.vertices().nodesCount(), sizeof(UCHAR))); + std::unique_ptr colorMapP(new UCHAR[mesh.vertices().nodesCount()]()); locals_::VertexesRecorder vertexesRecorder(vertexes); std::stack verticesQueue; diff --git a/toonz/sources/tnztools/pumptool.cpp b/toonz/sources/tnztools/pumptool.cpp index 2dd0304..f6f8fa8 100644 --- a/toonz/sources/tnztools/pumptool.cpp +++ b/toonz/sources/tnztools/pumptool.cpp @@ -546,7 +546,7 @@ void PumpTool::onLeave() { //***************************************************************************** double PumpTool::actionRadius(double strokeLength) { - double toolSize = std::max(m_toolSize.getValue(), 5.0); + double toolSize = m_toolSize.getValue(); double toolPercent = toolSize * 0.01; double interpolationVal = pow(toolPercent, 5); double indipendentValue = 7.0 * toolSize; diff --git a/toonz/sources/tnztools/rastererasertool.cpp b/toonz/sources/tnztools/rastererasertool.cpp index 8190503..8b86cdc 100644 --- a/toonz/sources/tnztools/rastererasertool.cpp +++ b/toonz/sources/tnztools/rastererasertool.cpp @@ -4,7 +4,6 @@ #include "tools/toolutils.h" #include "tools/cursors.h" #include "tools/tool.h" -#include "tools/toolutils.h" #include "tools/toolhandle.h" #include "bluredbrush.h" @@ -761,7 +760,7 @@ void EraserTool::multiUpdate(const TXshSimpleLevelP &level, TFrameId firstFid, TRectD lastRect) { bool backward = false; if (firstFid > lastFid) { - tswap(firstFid, lastFid); + std::swap(firstFid, lastFid); backward = true; } assert(firstFid <= lastFid); @@ -980,15 +979,15 @@ void EraserTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { TPointD rasCenter = ti->getRaster()->getCenterD(); if (m_eraseType.getValue() == RECTERASE) { TRectD oldRect = m_selectingRect; - if (oldRect.x0 > oldRect.x1) tswap(oldRect.x1, oldRect.x0); - if (oldRect.y0 > oldRect.y1) tswap(oldRect.y1, oldRect.y0); + if (oldRect.x0 > oldRect.x1) std::swap(oldRect.x1, oldRect.x0); + if (oldRect.y0 > oldRect.y1) std::swap(oldRect.y1, oldRect.y0); m_selectingRect.x1 = pos.x; m_selectingRect.y1 = pos.y; invalidateRect = m_selectingRect; if (invalidateRect.x0 > invalidateRect.x1) - tswap(invalidateRect.x1, invalidateRect.x0); + std::swap(invalidateRect.x1, invalidateRect.x0); if (invalidateRect.y0 > invalidateRect.y1) - tswap(invalidateRect.y1, invalidateRect.y0); + std::swap(invalidateRect.y1, invalidateRect.y0); invalidateRect += oldRect; invalidate(invalidateRect.enlarge(2)); } @@ -1113,9 +1112,9 @@ void EraserTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) { if (TToonzImageP ti = image) { if (m_eraseType.getValue() == RECTERASE) { if (m_selectingRect.x0 > m_selectingRect.x1) - tswap(m_selectingRect.x1, m_selectingRect.x0); + std::swap(m_selectingRect.x1, m_selectingRect.x0); if (m_selectingRect.y0 > m_selectingRect.y1) - tswap(m_selectingRect.y1, m_selectingRect.y0); + std::swap(m_selectingRect.y1, m_selectingRect.y0); if (m_multi.getValue()) { TTool::Application *app = TTool::getApplication(); @@ -1560,7 +1559,7 @@ void EraserTool::multiAreaEraser(const TXshSimpleLevelP &sl, TFrameId &firstFid, bool backward = false; if (firstFid > lastFid) { - tswap(firstFid, lastFid); + std::swap(firstFid, lastFid); backward = true; } assert(firstFid <= lastFid); diff --git a/toonz/sources/tnztools/rasterselection.cpp b/toonz/sources/tnztools/rasterselection.cpp index 206c209..886aee4 100644 --- a/toonz/sources/tnztools/rasterselection.cpp +++ b/toonz/sources/tnztools/rasterselection.cpp @@ -24,7 +24,6 @@ #include "toonz/toonzscene.h" #include "toonz/tcamera.h" #include "toonz/trasterimageutils.h" -#include "toonz/toonzimageutils.h" #include #include @@ -1160,9 +1159,12 @@ void RasterSelection::pasteSelection(const RasterImageData *riData) { void RasterSelection::pasteSelection() { TTool::Application *app = TTool::getApplication(); TTool *tool = app->getCurrentTool()->getTool(); - TImageP image = tool->getImage(true); - m_currentImage = image; - m_fid = tool->getCurrentFid(); + TImageP image = tool->touchImage(); + + if (!image) return; + + m_currentImage = image; + m_fid = tool->getCurrentFid(); QClipboard *clipboard = QApplication::clipboard(); const RasterImageData *riData = diff --git a/toonz/sources/tnztools/rastertapetool.cpp b/toonz/sources/tnztools/rastertapetool.cpp index 51b6e9c..109e294 100644 --- a/toonz/sources/tnztools/rastertapetool.cpp +++ b/toonz/sources/tnztools/rastertapetool.cpp @@ -301,7 +301,7 @@ public: TStroke *firstStroke = 0, TStroke *lastStroke = 0) { bool backward = false; if (firstFid > lastFid) { - tswap(firstFid, lastFid); + std::swap(firstFid, lastFid); backward = true; } assert(firstFid <= lastFid); @@ -360,8 +360,8 @@ public: int r1 = lastFrameId.getNumber(); if (r0 > r1) { - tswap(r0, r1); - tswap(firstFrameId, lastFrameId); + std::swap(r0, r1); + std::swap(firstFrameId, lastFrameId); } if ((r1 - r0) < 2) return; @@ -387,9 +387,9 @@ public: /*-- Rectの座標の向きを揃える --*/ if (m_selectingRect.x0 > m_selectingRect.x1) - tswap(m_selectingRect.x1, m_selectingRect.x0); + std::swap(m_selectingRect.x1, m_selectingRect.x0); if (m_selectingRect.y0 > m_selectingRect.y1) - tswap(m_selectingRect.y1, m_selectingRect.y0); + std::swap(m_selectingRect.y1, m_selectingRect.y0); TTool::Application *app = TTool::getApplication(); diff --git a/toonz/sources/tnztools/selectiontool.cpp b/toonz/sources/tnztools/selectiontool.cpp index 4238c64..0d98fe3 100644 --- a/toonz/sources/tnztools/selectiontool.cpp +++ b/toonz/sources/tnztools/selectiontool.cpp @@ -117,7 +117,7 @@ FourPoints DragSelectionTool::FourPoints::orderedPoints() const { int index = tminPoint(allPoints[minXindex1], points[minXindex2], false); TPointD newPoint1 = allPoints[minXindex1]; TPointD newPoint2 = points[minXindex2]; - if (index == 1) tswap(newPoint1, newPoint2); + if (index == 1) std::swap(newPoint1, newPoint2); newPoints.setP00(newPoint1); newPoints.setP01(newPoint2); @@ -732,7 +732,7 @@ TPointD DragSelectionTool::Scale::getNewCenter(int index, const FourPoints bbox, m_deformTool->getNextPointIndex(m_deformTool->getNextPointIndex(index)); yIndex = index; } - if (index % 2 == 1) tswap(xIndex, yIndex); + if (index % 2 == 1) std::swap(xIndex, yIndex); FourPoints xBbox = bboxScale(xIndex, bbox, m_startCenter); TPointD xCenter = getScaledPoint( xIndex, xBbox, scaleValue, diff --git a/toonz/sources/tnztools/shifttracetool.cpp b/toonz/sources/tnztools/shifttracetool.cpp new file mode 100644 index 0000000..a4f3647 --- /dev/null +++ b/toonz/sources/tnztools/shifttracetool.cpp @@ -0,0 +1,603 @@ + + +#include "shifttracetool.h" +#include "toonz/onionskinmask.h" +#include "toonz/tonionskinmaskhandle.h" +#include "tools/cursors.h" +#include "timage.h" +#include "trasterimage.h" +#include "ttoonzimage.h" +#include "tvectorimage.h" +#include "toonz/txsheet.h" +#include "toonz/txshcell.h" +#include "toonz/txsheethandle.h" +#include "toonz/tframehandle.h" +#include "toonz/tcolumnhandle.h" +#include "toonz/txshlevelhandle.h" +#include "tools/toolhandle.h" +#include "toonz/txshsimplelevel.h" +#include "toonz/dpiscale.h" +#include "toonz/stage.h" +#include "tpixel.h" +#include "toonzqt/menubarcommand.h" + +#include "toonz/preferences.h" +#include "toonzqt/gutil.h" + +#include "tgl.h" +#include +#include + +//============================================================================= + +static bool circumCenter(TPointD &out, const TPointD &a, const TPointD &b, + const TPointD &c) { + double d = 2 * (a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)); + if (fabs(d) < 0.0001) { + out = TPointD(); + return false; + } + out.x = ((a.y * a.y + a.x * a.x) * (b.y - c.y) + + (b.y * b.y + b.x * b.x) * (c.y - a.y) + + (c.y * c.y + c.x * c.x) * (a.y - b.y)) / + d; + out.y = ((a.y * a.y + a.x * a.x) * (c.x - b.x) + + (b.y * b.y + b.x * b.x) * (a.x - c.x) + + (c.y * c.y + c.x * c.x) * (b.x - a.x)) / + d; + return true; +} + +//============================================================================= + +ShiftTraceTool::ShiftTraceTool() + : TTool("T_ShiftTrace") + , m_ghostIndex(0) + , m_curveStatus(NoCurve) + , m_gadget(NoGadget) + , m_highlightedGadget(NoGadget) { + bind(TTool::AllTargets); // Deals with tool deactivation internally +} + +void ShiftTraceTool::clearData() { + m_ghostIndex = 0; + m_curveStatus = NoCurve; + m_gadget = NoGadget; + m_highlightedGadget = NoGadget; + + m_box = TRectD(); + for (int i = 0; i < 2; i++) { + m_row[i] = -1; + m_aff[i] = TAffine(); + m_center[i] = TPointD(); + } +} + +void ShiftTraceTool::updateBox() { + if (m_ghostIndex < 0 || 2 <= m_ghostIndex || m_row[m_ghostIndex] < 0) return; + + TImageP img; + + TApplication *app = TTool::getApplication(); + if (app->getCurrentFrame()->isEditingScene()) { + int col = app->getCurrentColumn()->getColumnIndex(); + int row = m_row[m_ghostIndex]; + TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); + + TXshCell cell = xsh->getCell(row, col); + TXshSimpleLevel *sl = cell.getSimpleLevel(); + if (sl) { + m_dpiAff = getDpiAffine(sl, cell.m_frameId); + img = cell.getImage(false); + } + } + // on editing level + else { + TXshLevel *level = app->getCurrentLevel()->getLevel(); + if (!level) return; + TXshSimpleLevel *sl = level->getSimpleLevel(); + if (!sl) return; + + const TFrameId &ghostFid = sl->index2fid(m_row[m_ghostIndex]); + m_dpiAff = getDpiAffine(sl, ghostFid); + img = sl->getFrame(ghostFid, false); + } + + if (img) { + if (TRasterImageP ri = img) { + TRasterP ras = ri->getRaster(); + m_box = (convert(ras->getBounds()) - ras->getCenterD()) * + ri->getSubsampling(); + } else if (TToonzImageP ti = img) { + TRasterP ras = ti->getRaster(); + m_box = (convert(ras->getBounds()) - ras->getCenterD()) * + ti->getSubsampling(); + } else if (TVectorImageP vi = img) { + m_box = vi->getBBox(); + } + } +} + +void ShiftTraceTool::updateData() { + m_box = TRectD(); + for (int i = 0; i < 2; i++) m_row[i] = -1; + m_dpiAff = TAffine(); + TApplication *app = TTool::getApplication(); + + OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask(); + int previousOffset = osm.getShiftTraceGhostFrameOffset(0); + int forwardOffset = osm.getShiftTraceGhostFrameOffset(1); + // we must find the prev (m_row[0]) and next (m_row[1]) reference images + // (either might not exist) + // see also stage.cpp, StageBuilder::addCellWithOnionSkin + if (app->getCurrentFrame()->isEditingScene()) { + TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); + int row = app->getCurrentFrame()->getFrame(); + int col = app->getCurrentColumn()->getColumnIndex(); + TXshCell cell = xsh->getCell(row, col); + int r; + r = row + previousOffset; + if (r >= 0 && xsh->getCell(r, col) != cell && + (cell.getSimpleLevel() == 0 || + xsh->getCell(r, col).getSimpleLevel() == cell.getSimpleLevel())) { + m_row[0] = r; + } + + r = row + forwardOffset; + if (r >= 0 && xsh->getCell(r, col) != cell && + (cell.getSimpleLevel() == 0 || + xsh->getCell(r, col).getSimpleLevel() == cell.getSimpleLevel())) { + m_row[1] = r; + } + } + // on editing level + else { + TXshLevel *level = app->getCurrentLevel()->getLevel(); + if (level) { + TXshSimpleLevel *sl = level->getSimpleLevel(); + if (sl) { + TFrameId fid = app->getCurrentFrame()->getFid(); + int row = sl->guessIndex(fid); + m_row[0] = row + previousOffset; + m_row[1] = row + forwardOffset; + } + } + } + updateBox(); +} + +// +// Compute m_aff[0] and m_aff[1] according to the current curve +// +void ShiftTraceTool::updateCurveAffs() { + if (m_curveStatus != ThreePointsCurve) { + m_aff[0] = m_aff[1] = TAffine(); + } else { + double phi0 = 0, phi1 = 0; + TPointD center; + if (circumCenter(center, m_p0, m_p1, m_p2)) { + TPointD v0 = normalize(m_p0 - center); + TPointD v1 = normalize(m_p1 - center); + TPointD v2 = normalize(m_p2 - center); + TPointD u0(-v0.y, v0.x); + TPointD u1(-v1.y, v1.x); + phi0 = atan2((v2 * u0), (v2 * v0)) * 180.0 / 3.1415; + phi1 = atan2((v2 * u1), (v2 * v1)) * 180.0 / 3.1415; + } + m_aff[0] = TTranslation(m_p2 - m_p0) * TRotation(m_p0, phi0); + m_aff[1] = TTranslation(m_p2 - m_p1) * TRotation(m_p1, phi1); + } +} + +void ShiftTraceTool::updateGhost() { + OnionSkinMask osm = + TTool::getApplication()->getCurrentOnionSkin()->getOnionSkinMask(); + osm.setShiftTraceGhostAff(0, m_aff[0]); + osm.setShiftTraceGhostAff(1, m_aff[1]); + osm.setShiftTraceGhostCenter(0, m_center[0]); + osm.setShiftTraceGhostCenter(1, m_center[1]); + TTool::getApplication()->getCurrentOnionSkin()->setOnionSkinMask(osm); +} + +void ShiftTraceTool::reset() { + int ghostIndex = m_ghostIndex; + onActivate(); + invalidate(); + m_ghostIndex = ghostIndex; + + TTool::getApplication() + ->getCurrentTool() + ->notifyToolChanged(); // Refreshes toolbar values +} + +TAffine ShiftTraceTool::getGhostAff() { + if (0 <= m_ghostIndex && m_ghostIndex < 2) + return m_aff[m_ghostIndex] * m_dpiAff; + else + return TAffine(); +} + +void ShiftTraceTool::drawDot(const TPointD ¢er, double r, + const TPixel32 &color) { + tglColor(color); + tglDrawDisk(center, r); + glColor3d(0.2, 0.2, 0.2); + tglDrawCircle(center, r); +} + +void ShiftTraceTool::drawControlRect() { // TODO + if (m_ghostIndex < 0 || m_ghostIndex > 1) return; + int row = m_row[m_ghostIndex]; + if (row < 0) return; + + TRectD box = m_box; + if (box.isEmpty()) return; + glPushMatrix(); + tglMultMatrix(getGhostAff()); + + TPixel32 color; + + // draw onion-colored rectangle to indicate which ghost is grabbed + { + TPixel32 frontOniColor, backOniColor; + bool inksOnly; + Preferences::instance()->getOnionData(frontOniColor, backOniColor, + inksOnly); + color = (m_ghostIndex == 0) ? backOniColor : frontOniColor; + double unit = sqrt(tglGetPixelSize2()); + unit *= getDevPixRatio(); + TRectD coloredBox = box.enlarge(3.0 * unit); + tglColor(color); + glBegin(GL_LINE_STRIP); + glVertex2d(coloredBox.x0, coloredBox.y0); + glVertex2d(coloredBox.x1, coloredBox.y0); + glVertex2d(coloredBox.x1, coloredBox.y1); + glVertex2d(coloredBox.x0, coloredBox.y1); + glVertex2d(coloredBox.x0, coloredBox.y0); + glEnd(); + } + + color = m_highlightedGadget == TranslateGadget + ? TPixel32(200, 100, 100) + : m_highlightedGadget == RotateGadget ? TPixel32(100, 200, 100) + : TPixel32(120, 120, 120); + tglColor(color); + glBegin(GL_LINE_STRIP); + glVertex2d(box.x0, box.y0); + glVertex2d(box.x1, box.y0); + glVertex2d(box.x1, box.y1); + glVertex2d(box.x0, box.y1); + glVertex2d(box.x0, box.y0); + glEnd(); + color = m_highlightedGadget == ScaleGadget ? TPixel32(200, 100, 100) + : TPixel32::White; + double r = 4 * sqrt(tglGetPixelSize2()); + drawDot(box.getP00(), r, color); + drawDot(box.getP01(), r, color); + drawDot(box.getP10(), r, color); + drawDot(box.getP11(), r, color); + if (m_curveStatus == NoCurve) { + color = m_highlightedGadget == MoveCenterGadget ? TPixel32(200, 100, 100) + : TPixel32::White; + TPointD c = m_center[m_ghostIndex]; + drawDot(c, r, color); + } + glPopMatrix(); +} + +void ShiftTraceTool::drawCurve() { + if (m_curveStatus == NoCurve) return; + double r = 4 * sqrt(tglGetPixelSize2()); + double u = getPixelSize(); + if (m_curveStatus == TwoPointsCurve) { + TPixel32 color = m_highlightedGadget == CurveP0Gadget + ? TPixel32(200, 100, 100) + : TPixel32::White; + drawDot(m_p0, r, color); + glColor3d(0.2, 0.2, 0.2); + tglDrawSegment(m_p0, m_p1); + drawDot(m_p1, r, TPixel32::Red); + } else if (m_curveStatus == ThreePointsCurve) { + TPixel32 color = m_highlightedGadget == CurveP0Gadget + ? TPixel32(200, 100, 100) + : TPixel32::White; + drawDot(m_p0, r, color); + color = m_highlightedGadget == CurveP1Gadget ? TPixel32(200, 100, 100) + : TPixel32::White; + drawDot(m_p1, r, color); + + glColor3d(0.2, 0.2, 0.2); + + TPointD center; + if (circumCenter(center, m_p0, m_p1, m_p2)) { + double radius = norm(center - m_p1); + glBegin(GL_LINE_STRIP); + int n = 100; + for (int i = 0; i < n; i++) { + double t = (double)i / n; + TPointD p = (1 - t) * m_p0 + t * m_p2; + p = center + radius * normalize(p - center); + tglVertex(p); + } + for (int i = 0; i < n; i++) { + double t = (double)i / n; + TPointD p = (1 - t) * m_p2 + t * m_p1; + p = center + radius * normalize(p - center); + tglVertex(p); + } + glEnd(); + } else { + tglDrawSegment(m_p0, m_p1); + } + color = m_highlightedGadget == CurvePmGadget ? TPixel32(200, 100, 100) + : TPixel32::White; + drawDot(m_p2, r, color); + } +} + +void ShiftTraceTool::onActivate() { + m_ghostIndex = 0; + m_curveStatus = NoCurve; + clearData(); + OnionSkinMask osm = + TTool::getApplication()->getCurrentOnionSkin()->getOnionSkinMask(); + m_aff[0] = osm.getShiftTraceGhostAff(0); + m_aff[1] = osm.getShiftTraceGhostAff(1); + m_center[0] = osm.getShiftTraceGhostCenter(0); + m_center[1] = osm.getShiftTraceGhostCenter(1); +} + +void ShiftTraceTool::onDeactivate() { + QAction *action = CommandManager::instance()->getAction("MI_EditShift"); + action->setChecked(false); +} + +ShiftTraceTool::GadgetId ShiftTraceTool::getGadget(const TPointD &p) { + std::vector> gadgets; + gadgets.push_back(std::make_pair(m_p0, CurveP0Gadget)); + gadgets.push_back(std::make_pair(m_p1, CurveP1Gadget)); + gadgets.push_back(std::make_pair(m_p2, CurvePmGadget)); + TAffine aff = getGhostAff(); + double pixelSize = getPixelSize(); + double d = 15 * pixelSize; // offset for rotation handle + if (0 <= m_ghostIndex && m_ghostIndex < 2) { + gadgets.push_back(std::make_pair(aff * m_box.getP00(), ScaleGadget)); + gadgets.push_back(std::make_pair(aff * m_box.getP01(), ScaleGadget)); + gadgets.push_back(std::make_pair(aff * m_box.getP10(), ScaleGadget)); + gadgets.push_back(std::make_pair(aff * m_box.getP11(), ScaleGadget)); + gadgets.push_back( + std::make_pair(aff * m_center[m_ghostIndex], MoveCenterGadget)); + } + int k = -1; + double minDist2 = pow(10 * pixelSize, 2); + for (int i = 0; i < (int)gadgets.size(); i++) { + double d2 = norm2(gadgets[i].first - p); + if (d2 < minDist2) { + minDist2 = d2; + k = i; + } + } + if (k >= 0) return gadgets[k].second; + + // rect-point + if (0 <= m_ghostIndex && m_ghostIndex < 2) { + TPointD q = aff.inv() * p; + double big = 1.0e6; + double d = big, x = 0, y = 0; + if (m_box.x0 < q.x && q.x < m_box.x1) { + x = q.x; + double d0 = fabs(m_box.y0 - q.y); + double d1 = fabs(m_box.y1 - q.y); + if (d0 < d1) { + d = d0; + y = m_box.y0; + } else { + d = d1; + y = m_box.y1; + } + } + if (m_box.y0 < q.y && q.y < m_box.y1) { + double d0 = fabs(m_box.x0 - q.x); + double d1 = fabs(m_box.x1 - q.x); + if (d0 < d) { + d = d0; + y = q.y; + x = m_box.x0; + } + if (d1 < d) { + d = d1; + y = q.y; + x = m_box.x1; + } + } + if (d < big) { + TPointD pp = aff * TPointD(x, y); + double d = norm(p - pp); + if (d < 10 * getPixelSize()) { + if (m_box.contains(q)) + return TranslateGadget; + else + return RotateGadget; + } + } + if (m_box.contains(q)) + return NoGadget_InBox; + else + return NoGadget; + } + return NoGadget; +} + +void ShiftTraceTool::mouseMove(const TPointD &pos, const TMouseEvent &e) { + GadgetId highlightedGadget = getGadget(pos); + if (highlightedGadget != m_highlightedGadget) { + m_highlightedGadget = highlightedGadget; + invalidate(); + } +} + +void ShiftTraceTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { + m_gadget = m_highlightedGadget; + m_oldPos = m_startPos = pos; + + bool notify = false; + + if (m_gadget == NoGadget || m_gadget == NoGadget_InBox) { + if (!e.isCtrlPressed()) { + if (m_gadget == NoGadget_InBox) + m_gadget = TranslateGadget; + else + m_gadget = RotateGadget; + // m_curveStatus = NoCurve; + } + int row = getViewer()->posToRow(e.m_pos, 5 * getPixelSize(), false, true); + if (row >= 0) { + int index = -1; + TApplication *app = TTool::getApplication(); + if (app->getCurrentFrame()->isEditingScene()) { + int currentRow = getFrame(); + if (m_row[0] >= 0 && row < currentRow) + index = 0; + else if (m_row[1] >= 0 && row > currentRow) + index = 1; + } else { + if (m_row[0] == row) + index = 0; + else if (m_row[1] == row) + index = 1; + } + + if (index >= 0) { + m_ghostIndex = index; + updateBox(); + m_gadget = TranslateGadget; + m_highlightedGadget = TranslateGadget; + notify = true; + } + } + } + + m_oldAff = m_aff[m_ghostIndex]; + invalidate(); + + if (notify) { + TTool::getApplication() + ->getCurrentTool() + ->notifyToolChanged(); // Refreshes toolbar values + } +} + +void ShiftTraceTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { + if (m_gadget == NoGadget || m_gadget == NoGadget_InBox) { + if (norm(pos - m_oldPos) > 10 * getPixelSize()) { + m_curveStatus = TwoPointsCurve; + m_p0 = m_oldPos; + m_gadget = CurveP1Gadget; + } + } + + if (isCurveGadget(m_gadget)) { + if (m_gadget == CurveP0Gadget) + m_p0 = pos; + else if (m_gadget == CurveP1Gadget) + m_p1 = pos; + else + m_p2 = pos; + updateCurveAffs(); + } else if (m_gadget == RotateGadget) { + TAffine aff = getGhostAff(); + TPointD c = aff * m_center[m_ghostIndex]; + TPointD a = m_oldPos - c; + TPointD b = pos - c; + m_oldPos = pos; + TPointD u = normalize(a); + double phi = + atan2(-u.y * b.x + u.x * b.y, u.x * b.x + u.y * b.y) * 180.0 / 3.14153; + + TPointD imgC = aff * m_center[m_ghostIndex]; + + m_aff[m_ghostIndex] = TRotation(imgC, phi) * m_aff[m_ghostIndex]; + } else if (m_gadget == MoveCenterGadget) { + TAffine aff = getGhostAff().inv(); + TPointD delta = aff * pos - aff * m_oldPos; + m_oldPos = pos; + m_center[m_ghostIndex] += delta; + } else if (m_gadget == TranslateGadget) { + TPointD delta = pos - m_oldPos; + m_oldPos = pos; + m_aff[m_ghostIndex] = TTranslation(delta) * m_aff[m_ghostIndex]; + } else if (m_gadget == ScaleGadget) { + TAffine aff = getGhostAff(); + TPointD c = aff * m_center[m_ghostIndex]; + TPointD a = m_oldPos - c; + TPointD b = pos - c; + if (e.isShiftPressed()) + m_aff[m_ghostIndex] = m_oldAff * TScale(b.x / a.x, b.y / a.y); + else { + double scale = std::max(b.x / a.x, b.y / a.y); + m_aff[m_ghostIndex] = m_oldAff * TScale(scale, scale); + } + } + + updateGhost(); + invalidate(); +} + +void ShiftTraceTool::leftButtonUp(const TPointD &pos, const TMouseEvent &) { + if (CurveP0Gadget <= m_gadget && m_gadget <= CurvePmGadget) { + if (m_curveStatus == TwoPointsCurve) { + m_p2 = (m_p0 + m_p1) * 0.5; + m_curveStatus = ThreePointsCurve; + updateCurveAffs(); + updateGhost(); + + m_center[0] = (m_aff[0] * m_dpiAff).inv() * m_p2; + m_center[1] = (m_aff[1] * m_dpiAff).inv() * m_p2; + } + } + m_gadget = NoGadget; + invalidate(); + + TTool::getApplication() + ->getCurrentTool() + ->notifyToolChanged(); // Refreshes toolbar values +} + +void ShiftTraceTool::draw() { + updateData(); + drawControlRect(); + drawCurve(); +} + +int ShiftTraceTool::getCursorId() const { + if (m_highlightedGadget == RotateGadget || m_highlightedGadget == NoGadget) + return ToolCursor::RotateCursor; + else if (m_highlightedGadget == ScaleGadget) + return ToolCursor::ScaleCursor; + else if (isCurveGadget(m_highlightedGadget)) + return ToolCursor::PinchCursor; + else // Curve Points, TranslateGadget, NoGadget_InBox + return ToolCursor::MoveCursor; +} + +bool ShiftTraceTool::isEventAcceptable(QEvent *e) { + // F1, F2 and F3 keys are used for flipping + QKeyEvent *keyEvent = static_cast(e); + int key = keyEvent->key(); + return (Qt::Key_F1 <= key && key <= Qt::Key_F3); +} + +void ShiftTraceTool::onLeave() { + OnionSkinMask osm = + TTool::getApplication()->getCurrentOnionSkin()->getOnionSkinMask(); + osm.clearGhostFlipKey(); + TTool::getApplication()->getCurrentOnionSkin()->setOnionSkinMask(osm); +} + +void ShiftTraceTool::setCurrentGhostIndex(int index) { + m_ghostIndex = index; + updateBox(); + invalidate(); +} + +ShiftTraceTool shiftTraceTool; diff --git a/toonz/sources/tnztools/shifttracetool.h b/toonz/sources/tnztools/shifttracetool.h new file mode 100644 index 0000000..3fd6412 --- /dev/null +++ b/toonz/sources/tnztools/shifttracetool.h @@ -0,0 +1,82 @@ +#pragma once + +#include "tools/tool.h" + +class ShiftTraceTool final : public TTool { +public: + enum CurveStatus { + NoCurve, + TwoPointsCurve, // just during the first click&drag + ThreePointsCurve + }; + + enum GadgetId { + NoGadget, + NoGadget_InBox, + CurveP0Gadget, + CurveP1Gadget, + CurvePmGadget, + MoveCenterGadget, + RotateGadget, + TranslateGadget, + ScaleGadget + }; + inline bool isCurveGadget(GadgetId id) const { + return CurveP0Gadget <= id && id <= CurvePmGadget; + } + +private: + TPointD m_oldPos, m_startPos; + int m_ghostIndex; + TPointD m_p0, m_p1, m_p2; + + CurveStatus m_curveStatus; + GadgetId m_gadget; + GadgetId m_highlightedGadget; + + TRectD m_box; + TAffine m_dpiAff; + int m_row[2]; + TAffine m_aff[2]; + TPointD m_center[2]; + + TAffine m_oldAff; + +public: + ShiftTraceTool(); + + ToolType getToolType() const override { return GenericTool; } + + void clearData(); + void updateData(); + void updateBox(); + void updateCurveAffs(); + void updateGhost(); + + void reset() override; + + void mouseMove(const TPointD &, const TMouseEvent &e) override; + void leftButtonDown(const TPointD &, const TMouseEvent &) override; + void leftButtonDrag(const TPointD &, const TMouseEvent &) override; + void leftButtonUp(const TPointD &, const TMouseEvent &) override; + void draw() override; + + TAffine getGhostAff(); + GadgetId getGadget(const TPointD &); + void drawDot(const TPointD ¢er, double r, + const TPixel32 &color = TPixel32::White); + void drawControlRect(); + void drawCurve(); + + void onActivate() override; + void onDeactivate() override; + + void onLeave() override; + + bool isEventAcceptable(QEvent *e) override; + + int getCursorId() const override; + + int getCurrentGhostIndex() { return m_ghostIndex; } + void setCurrentGhostIndex(int index); +}; \ No newline at end of file diff --git a/toonz/sources/tnztools/toolhandle.cpp b/toonz/sources/tnztools/toolhandle.cpp index 1143db9..06ba72b 100644 --- a/toonz/sources/tnztools/toolhandle.cpp +++ b/toonz/sources/tnztools/toolhandle.cpp @@ -6,7 +6,6 @@ #include "tools/toolcommandids.h" #include "timage.h" //#include "tapp.h" -#include "toonz/stage2.h" #include "toonzqt/menubarcommand.h" #include #include diff --git a/toonz/sources/tnztools/tooloptions.cpp b/toonz/sources/tnztools/tooloptions.cpp index 1cc30f6..dbc4cce 100644 --- a/toonz/sources/tnztools/tooloptions.cpp +++ b/toonz/sources/tnztools/tooloptions.cpp @@ -10,12 +10,14 @@ #include "selectiontool.h" #include "vectorselectiontool.h" #include "rasterselectiontool.h" -#include "brushtool.h" +#include "toonzrasterbrushtool.h" #include "fullcolorbrushtool.h" +#include "toonzvectorbrushtool.h" #include "tooloptionscontrols.h" //#include "rgbpickertool.h" #include "rulertool.h" +#include "shifttracetool.h" // TnzQt includes #include "toonzqt/dvdialog.h" @@ -36,6 +38,7 @@ #include "toonz/preferences.h" #include "toonz/tstageobjecttree.h" #include "toonz/mypaintbrushstyle.h" +#include "toonz/tonionskinmaskhandle.h" // TnzCore includes #include "tproperty.h" @@ -53,7 +56,6 @@ #include #include #include -#include #include #include #include @@ -365,6 +367,17 @@ void ToolOptionControlBuilder::visit(TEnumProperty *p) { break; } + case FONTCOMBOBOX: { + if (p->getQStringName() != "") { + QLabel *label = addLabel(p); + m_panel->addLabel(p->getName(), label); + } + ToolOptionFontCombo *obj = new ToolOptionFontCombo(m_tool, p, m_toolHandle); + control = obj; + widget = obj; + break; + } + case COMBOBOX: default: { if (p->getQStringName() != "") { @@ -1526,22 +1539,28 @@ TypeToolOptionsBox::TypeToolOptionsBox(QWidget *parent, TTool *tool, assert(props->getPropertyCount() > 0); ToolOptionControlBuilder builder(this, tool, pltHandle, toolHandle); + builder.setEnumWidgetType(ToolOptionControlBuilder::FONTCOMBOBOX); if (tool && tool->getProperties(0)) tool->getProperties(0)->accept(builder); + builder.setEnumWidgetType(ToolOptionControlBuilder::COMBOBOX); + if (tool && tool->getProperties(1)) tool->getProperties(1)->accept(builder); m_layout->addStretch(0); bool ret = true; - ToolOptionCombo *fontField = - dynamic_cast(m_controls.value("Font:")); + + ToolOptionFontCombo *fontField = + dynamic_cast(m_controls.value("Font:")); ret &&connect(fontField, SIGNAL(currentIndexChanged(int)), this, SLOT(onFieldChanged())); -#ifndef MACOSX + //#ifndef MACOSX ToolOptionCombo *styleField = dynamic_cast(m_controls.value("Style:")); ret &&connect(styleField, SIGNAL(currentIndexChanged(int)), this, SLOT(onFieldChanged())); -#endif + ret &&connect(toolHandle, SIGNAL(toolComboBoxListChanged(std::string)), + styleField, SLOT(reloadComboBoxList(std::string))); + //#endif ToolOptionCombo *sizeField = dynamic_cast(m_controls.value("Size:")); @@ -1848,9 +1867,18 @@ void BrushToolOptionsBox::filterControls() { // show or hide widgets which modify imported brush (mypaint) bool showModifiers = false; - if (FullColorBrushTool *fullColorBrushTool = - dynamic_cast(m_tool)) + if (m_tool->getTargetType() & TTool::RasterImage) { + FullColorBrushTool *fullColorBrushTool = + dynamic_cast(m_tool); showModifiers = fullColorBrushTool->getBrushStyle(); + } else if (m_tool->getTargetType() & TTool::ToonzImage) { + ToonzRasterBrushTool *toonzRasterBrushTool = + dynamic_cast(m_tool); + showModifiers = toonzRasterBrushTool->isMyPaintStyleSelected(); + } else { // (m_tool->getTargetType() & TTool::Vectors) + m_snapSensitivityCombo->setHidden(!m_snapCheckbox->isChecked()); + return; + } for (QMap::iterator it = m_labels.begin(); it != m_labels.end(); it++) { @@ -1868,9 +1896,6 @@ void BrushToolOptionsBox::filterControls() { if (QWidget *widget = dynamic_cast(it.value())) widget->setVisible(visible); } - if (m_tool->getTargetType() & TTool::Vectors) { - m_snapSensitivityCombo->setHidden(!m_snapCheckbox->isChecked()); - } } //----------------------------------------------------------------------------- @@ -1912,9 +1937,12 @@ void BrushToolOptionsBox::onAddPreset() { m_presetNamePopup->removeName(); switch (m_tool->getTargetType() & TTool::CommonImages) { - case TTool::VectorImage: + case TTool::VectorImage: { + static_cast(m_tool)->addPreset(name); + break; + } case TTool::ToonzImage: { - static_cast(m_tool)->addPreset(name); + static_cast(m_tool)->addPreset(name); break; } @@ -1931,9 +1959,12 @@ void BrushToolOptionsBox::onAddPreset() { void BrushToolOptionsBox::onRemovePreset() { switch (m_tool->getTargetType() & TTool::CommonImages) { - case TTool::VectorImage: + case TTool::VectorImage: { + static_cast(m_tool)->removePreset(); + break; + } case TTool::ToonzImage: { - static_cast(m_tool)->removePreset(); + static_cast(m_tool)->removePreset(); break; } @@ -2480,6 +2511,135 @@ void StylePickerToolOptionsBox::updateRealTimePickLabel(const int ink, } //============================================================================= +// ShiftTraceToolOptionBox +//----------------------------------------------------------------------------- + +ShiftTraceToolOptionBox::ShiftTraceToolOptionBox(QWidget *parent, TTool *tool) + : ToolOptionsBox(parent), m_tool(tool) { + setFrameStyle(QFrame::StyledPanel); + setFixedHeight(26); + + m_prevFrame = new QFrame(this); + m_afterFrame = new QFrame(this); + + m_resetPrevGhostBtn = new QPushButton(tr("Reset Previous"), this); + m_resetAfterGhostBtn = new QPushButton(tr("Reset Following"), this); + + m_prevRadioBtn = new QRadioButton(tr("Previous Drawing"), this); + m_afterRadioBtn = new QRadioButton(tr("Following Drawing"), this); + + m_prevFrame->setFixedSize(10, 21); + m_afterFrame->setFixedSize(10, 21); + + m_layout->addWidget(m_prevFrame, 0); + m_layout->addWidget(m_prevRadioBtn, 0); + m_layout->addWidget(m_resetPrevGhostBtn, 0); + + m_layout->addWidget(new DVGui::Separator("", this, false)); + + m_layout->addWidget(m_afterFrame, 0); + m_layout->addWidget(m_afterRadioBtn, 0); + m_layout->addWidget(m_resetAfterGhostBtn, 0); + + m_layout->addStretch(1); + + connect(m_resetPrevGhostBtn, SIGNAL(clicked(bool)), this, + SLOT(onResetPrevGhostBtnPressed())); + connect(m_resetAfterGhostBtn, SIGNAL(clicked(bool)), this, + SLOT(onResetAfterGhostBtnPressed())); + connect(m_prevRadioBtn, SIGNAL(clicked(bool)), this, + SLOT(onPrevRadioBtnClicked())); + connect(m_afterRadioBtn, SIGNAL(clicked(bool)), this, + SLOT(onAfterRadioBtnClicked())); + + updateStatus(); +} + +void ShiftTraceToolOptionBox::showEvent(QShowEvent *) { + TTool::Application *app = TTool::getApplication(); + connect(app->getCurrentOnionSkin(), SIGNAL(onionSkinMaskChanged()), this, + SLOT(updateColors())); + updateColors(); +} + +void ShiftTraceToolOptionBox::hideEvent(QShowEvent *) { + TTool::Application *app = TTool::getApplication(); + disconnect(app->getCurrentOnionSkin(), SIGNAL(onionSkinMaskChanged()), this, + SLOT(updateColors())); +} + +void ShiftTraceToolOptionBox::resetGhost(int index) { + TTool::Application *app = TTool::getApplication(); + OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask(); + osm.setShiftTraceGhostCenter(index, TPointD()); + osm.setShiftTraceGhostAff(index, TAffine()); + app->getCurrentOnionSkin()->setOnionSkinMask(osm); + app->getCurrentOnionSkin()->notifyOnionSkinMaskChanged(); + TTool *tool = app->getCurrentTool()->getTool(); + if (tool) tool->reset(); + + if (index == 0) + m_resetPrevGhostBtn->setDisabled(true); + else // index == 1 + m_resetAfterGhostBtn->setDisabled(true); +} + +void ShiftTraceToolOptionBox::onResetPrevGhostBtnPressed() { resetGhost(0); } + +void ShiftTraceToolOptionBox::onResetAfterGhostBtnPressed() { resetGhost(1); } + +void ShiftTraceToolOptionBox::updateColors() { + TPixel front, back; + bool ink; + Preferences::instance()->getOnionData(front, back, ink); + + m_prevFrame->setStyleSheet(QString("background:rgb(%1,%2,%3,255);") + .arg((int)back.r) + .arg((int)back.g) + .arg((int)back.b)); + m_afterFrame->setStyleSheet(QString("background:rgb(%1,%2,%3,255);") + .arg((int)front.r) + .arg((int)front.g) + .arg((int)front.b)); +} + +void ShiftTraceToolOptionBox::updateStatus() { + TTool::Application *app = TTool::getApplication(); + OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask(); + if (osm.getShiftTraceGhostAff(0).isIdentity() && + osm.getShiftTraceGhostCenter(0) == TPointD()) + m_resetPrevGhostBtn->setDisabled(true); + else + m_resetPrevGhostBtn->setEnabled(true); + + if (osm.getShiftTraceGhostAff(1).isIdentity() && + osm.getShiftTraceGhostCenter(1) == TPointD()) + m_resetAfterGhostBtn->setDisabled(true); + else + m_resetAfterGhostBtn->setEnabled(true); + + // Check the ghost index + ShiftTraceTool *stTool = (ShiftTraceTool *)m_tool; + if (!stTool) return; + if (stTool->getCurrentGhostIndex() == 0) + m_prevRadioBtn->setChecked(true); + else // ghostIndex == 1 + m_afterRadioBtn->setChecked(true); +} + +void ShiftTraceToolOptionBox::onPrevRadioBtnClicked() { + ShiftTraceTool *stTool = (ShiftTraceTool *)m_tool; + if (!stTool) return; + stTool->setCurrentGhostIndex(0); +} + +void ShiftTraceToolOptionBox::onAfterRadioBtnClicked() { + ShiftTraceTool *stTool = (ShiftTraceTool *)m_tool; + if (!stTool) return; + stTool->setCurrentGhostIndex(1); +} + +//============================================================================= // ToolOptions //----------------------------------------------------------------------------- @@ -2587,6 +2747,8 @@ void ToolOptions::onToolSwitched() { } else if (tool->getName() == T_StylePicker) panel = new StylePickerToolOptionsBox(0, tool, currPalette, currTool, app->getPaletteController()); + else if (tool->getName() == "T_ShiftTrace") + panel = new ShiftTraceToolOptionBox(this, tool); else panel = tool->createOptionsBox(); // Only this line should remain out // of that if/else monstrosity diff --git a/toonz/sources/tnztools/tooloptionscontrols.cpp b/toonz/sources/tnztools/tooloptionscontrols.cpp index f257158..bee24dc 100644 --- a/toonz/sources/tnztools/tooloptionscontrols.cpp +++ b/toonz/sources/tnztools/tooloptionscontrols.cpp @@ -571,8 +571,16 @@ ToolOptionCombo::ToolOptionCombo(TTool *tool, TEnumProperty *property, setSizeAdjustPolicy(QComboBox::AdjustToContents); connect(this, SIGNAL(activated(int)), this, SLOT(onActivated(int))); // synchronize the state with the same widgets in other tool option bars - if (toolHandle) + if (toolHandle) { connect(this, SIGNAL(activated(int)), toolHandle, SIGNAL(toolChanged())); + } +} + +//----------------------------------------------------------------------------- + +void ToolOptionCombo::reloadComboBoxList(std::string id) { + if (id == "" || m_property->getName() != id) return; + loadEntries(); } //----------------------------------------------------------------------------- @@ -682,6 +690,58 @@ void ToolOptionCombo::doOnActivated(int index) { //============================================================================= +ToolOptionFontCombo::ToolOptionFontCombo(TTool *tool, TEnumProperty *property, + ToolHandle *toolHandle) + : QFontComboBox() + , ToolOptionControl(tool, property->getName(), toolHandle) + , m_property(property) { + setMaximumWidth(250); + m_property->addListener(this); + setSizeAdjustPolicy(QFontComboBox::AdjustToContents); + connect(this, SIGNAL(activated(int)), this, SLOT(onActivated(int))); + // synchronize the state with the same widgets in other tool option bars + if (toolHandle) + connect(this, SIGNAL(activated(int)), toolHandle, SIGNAL(toolChanged())); + + updateStatus(); +} + +//----------------------------------------------------------------------------- + +void ToolOptionFontCombo::updateStatus() { + QString value = QString::fromStdWString(m_property->getValue()); + int index = findText(value); + if (index >= 0 && index != currentIndex()) setCurrentIndex(index); +} + +//----------------------------------------------------------------------------- + +void ToolOptionFontCombo::onActivated(int index) { + const TEnumProperty::Range &range = m_property->getRange(); + if (index < 0 || index >= (int)range.size()) return; + + std::wstring item = range[index]; + m_property->setValue(item); + notifyTool(); +} + +//----------------------------------------------------------------------------- + +void ToolOptionFontCombo::doShowPopup() { + if (!isInVisibleViewer(this)) return; + if (Preferences::instance()->getDropdownShortcutsCycleOptions()) { + const TEnumProperty::Range &range = m_property->getRange(); + int theIndex = currentIndex() + 1; + if (theIndex >= (int)range.size()) theIndex = 0; + onActivated(theIndex); + setCurrentIndex(theIndex); + } else { + if (isVisible()) showPopup(); + } +} + +//============================================================================= + ToolOptionPopupButton::ToolOptionPopupButton(TTool *tool, TEnumProperty *property) : PopupButton() @@ -808,15 +868,16 @@ void StyleIndexFieldAndChip::onValueChanged(const QString &changedText) { // Aware of both "current" and translated string if (!QString("current").contains(changedText) && !StyleIndexLineEdit::tr("current").contains(changedText)) { - int index = changedText.toInt(); - TPalette *plt = m_pltHandle->getPalette(); - int indexCount = plt->getStyleCount(); - if (index > indexCount) - style = QString::number(indexCount - 1); + int index = changedText.toInt(); + TPalette *plt = m_pltHandle->getPalette(); + if (plt && index > plt->getStyleCount()) + style = QString::number(plt->getStyleCount() - 1); else style = text(); - } - m_property->setValue(style.toStdWString()); + m_property->setValue(style.toStdWString()); + } else + m_property->setValue(changedText.toStdWString()); + repaint(); // synchronize the state with the same widgets in other tool option bars if (m_toolHandle) m_toolHandle->notifyToolChanged(); diff --git a/toonz/sources/tnztools/tooloptionscontrols.h b/toonz/sources/tnztools/tooloptionscontrols.h index 4e64808..6af4bbc 100644 --- a/toonz/sources/tnztools/tooloptionscontrols.h +++ b/toonz/sources/tnztools/tooloptionscontrols.h @@ -29,6 +29,7 @@ // Qt includes #include +#include #include #include #include @@ -202,7 +203,30 @@ protected: public: ToolOptionCombo(TTool *tool, TEnumProperty *property, ToolHandle *toolHandle = 0); + void updateStatus() override; + + TEnumProperty *getProperty() const { return m_property; } + +public slots: + void reloadComboBoxList(std::string); void loadEntries(); + void onActivated(int); + void doShowPopup(); + void doOnActivated(int); +}; + +//----------------------------------------------------------------------------- + +class ToolOptionFontCombo final : public QFontComboBox, + public ToolOptionControl { + Q_OBJECT + +protected: + TEnumProperty *m_property; + +public: + ToolOptionFontCombo(TTool *tool, TEnumProperty *property, + ToolHandle *toolHandle = 0); void updateStatus() override; TEnumProperty *getProperty() const { return m_property; } @@ -211,7 +235,6 @@ public slots: void onActivated(int); void doShowPopup(); - void doOnActivated(int); }; //----------------------------------------------------------------------------- @@ -580,7 +603,7 @@ protected: void mouseReleaseEvent(QMouseEvent *) override; public: - ClickableLabel(const QString &text, QWidget *parent = Q_NULLPTR, + ClickableLabel(const QString &text, QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); ~ClickableLabel(); diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.cpp b/toonz/sources/tnztools/toonzrasterbrushtool.cpp new file mode 100644 index 0000000..589e040 --- /dev/null +++ b/toonz/sources/tnztools/toonzrasterbrushtool.cpp @@ -0,0 +1,2305 @@ + + +#include "toonzrasterbrushtool.h" + +// TnzTools includes +#include "tools/toolhandle.h" +#include "tools/toolutils.h" +#include "tools/tooloptions.h" +#include "bluredbrush.h" + +// TnzQt includes +#include "toonzqt/dvdialog.h" +#include "toonzqt/imageutils.h" + +// TnzLib includes +#include "toonz/tobjecthandle.h" +#include "toonz/txsheethandle.h" +#include "toonz/txshlevelhandle.h" +#include "toonz/tframehandle.h" +#include "toonz/tcolumnhandle.h" +#include "toonz/txsheet.h" +#include "toonz/tstageobject.h" +#include "toonz/tstageobjectspline.h" +#include "toonz/rasterstrokegenerator.h" +#include "toonz/ttileset.h" +#include "toonz/txshsimplelevel.h" +#include "toonz/toonzimageutils.h" +#include "toonz/palettecontroller.h" +#include "toonz/stage2.h" +#include "toonz/preferences.h" +#include "toonz/tpalettehandle.h" +#include "toonz/mypaintbrushstyle.h" + +// TnzCore includes +#include "tstream.h" +#include "tcolorstyles.h" +#include "tvectorimage.h" +#include "tenv.h" +#include "tregion.h" +#include "tinbetween.h" + +#include "tgl.h" +#include "trop.h" + +// Qt includes +#include + +using namespace ToolUtils; + +TEnv::DoubleVar RasterBrushMinSize("InknpaintRasterBrushMinSize", 1); +TEnv::DoubleVar RasterBrushMaxSize("InknpaintRasterBrushMaxSize", 5); +TEnv::DoubleVar BrushSmooth("InknpaintBrushSmooth", 0); +TEnv::IntVar BrushDrawOrder("InknpaintBrushDrawOrder", 0); +TEnv::IntVar RasterBrushPencilMode("InknpaintRasterBrushPencilMode", 0); +TEnv::IntVar BrushPressureSensitivity("InknpaintBrushPressureSensitivity", 1); +TEnv::DoubleVar RasterBrushHardness("RasterBrushHardness", 100); +TEnv::DoubleVar RasterBrushModifierSize("RasterBrushModifierSize", 0); + +//------------------------------------------------------------------- +#define CUSTOM_WSTR L"" +//------------------------------------------------------------------- +// +// (Da mettere in libreria) : funzioni che spezzano una stroke +// nei suoi punti angolosi. Lo facciamo specialmente per limitare +// i problemi di fill. +// +//------------------------------------------------------------------- + +// +// Split a stroke in n+1 parts, according to n parameter values +// Input: +// stroke = stroke to split +// parameterValues[] = vector of parameters where I want to split the +// stroke +// assert: 0 ¶meterValues, + std::vector &strokes) { + TThickPoint p2; + std::vector points; + TThickPoint lastPoint = stroke->getControlPoint(0); + int n = parameterValues.size(); + int chunk; + double t; + int last_chunk = -1, startPoint = 0; + double lastLocT = 0; + + for (int i = 0; i < n; i++) { + points.push_back(lastPoint); // Add first point of the stroke + double w = + parameterValues[i]; // Global parameter. along the stroke 0<=w<=1 + stroke->getChunkAndT(w, chunk, + t); // t: local parameter in the chunk-th quadratic + + if (i == 0) + startPoint = 1; + else { + int indexAfterLastT = + stroke->getControlPointIndexAfterParameter(parameterValues[i - 1]); + startPoint = indexAfterLastT; + if ((indexAfterLastT & 1) && lastLocT != 1) startPoint++; + } + int endPoint = 2 * chunk + 1; + if (lastLocT != 1 && i > 0) { + if (last_chunk != chunk || t == 1) + points.push_back(p2); // If the last local t is not an extreme + // add the point p2 + } + + for (int j = startPoint; j < endPoint; j++) + points.push_back(stroke->getControlPoint(j)); + + TThickPoint p, A, B, C; + p = stroke->getPoint(w); + C = stroke->getControlPoint(2 * chunk + 2); + B = stroke->getControlPoint(2 * chunk + 1); + A = stroke->getControlPoint(2 * chunk); + p.thick = A.thick; + + if (last_chunk != chunk) { + TThickPoint p1 = (1 - t) * A + t * B; + points.push_back(p1); + p.thick = p1.thick; + } else { + if (t != 1) { + // If the i-th cut point belong to the same chunk of the (i-1)-th cut + // point. + double tInters = lastLocT / t; + TThickPoint p11 = (1 - t) * A + t * B; + TThickPoint p1 = (1 - tInters) * p11 + tInters * p; + points.push_back(p1); + p.thick = p1.thick; + } + } + + points.push_back(p); + + if (t != 1) p2 = (1 - t) * B + t * C; + + assert(points.size() & 1); + + // Add new stroke + TStroke *strokeAdd = new TStroke(points); + strokeAdd->setStyle(stroke->getStyle()); + strokeAdd->outlineOptions() = stroke->outlineOptions(); + strokes.push_back(strokeAdd); + + lastPoint = p; + last_chunk = chunk; + lastLocT = t; + points.clear(); + } + // Add end stroke + points.push_back(lastPoint); + + if (lastLocT != 1) points.push_back(p2); + + startPoint = + stroke->getControlPointIndexAfterParameter(parameterValues[n - 1]); + if ((stroke->getControlPointIndexAfterParameter(parameterValues[n - 1]) & + 1) && + lastLocT != 1) + startPoint++; + for (int j = startPoint; j < stroke->getControlPointCount(); j++) + points.push_back(stroke->getControlPoint(j)); + + assert(points.size() & 1); + TStroke *strokeAdd = new TStroke(points); + strokeAdd->setStyle(stroke->getStyle()); + strokeAdd->outlineOptions() = stroke->outlineOptions(); + strokes.push_back(strokeAdd); + points.clear(); +} + +// Compute Parametric Curve Curvature +// By Formula: +// k(t)=(|p'(t) x p''(t)|)/Norm2(p')^3 +// p(t) is parametric curve +// Input: +// dp = First Derivate. +// ddp = Second Derivate +// Output: +// return curvature value. +// Note: if the curve is a single point (that's dp=0) or it is a straight +// line (that's ddp=0) return 0 + +static double curvature(TPointD dp, TPointD ddp) { + if (dp == TPointD(0, 0)) + return 0; + else + return fabs(cross(dp, ddp) / pow(norm2(dp), 1.5)); +} + +// Find the max curvature points of a stroke. +// Input: +// stroke. +// angoloLim = Value (radians) of the Corner between two tangent vector. +// Up this value the two corner can be considered angular. +// curvMaxLim = Value of the max curvature. +// Up this value the point can be considered a max curvature +// point. +// Output: +// parameterValues = vector of max curvature parameter points + +static void findMaxCurvPoints(TStroke *stroke, const float &angoloLim, + const float &curvMaxLim, + std::vector ¶meterValues) { + TPointD tg1, tg2; // Tangent vectors + + TPointD dp, ddp; // First and Second derivate. + + parameterValues.clear(); + int cpn = stroke ? stroke->getControlPointCount() : 0; + for (int j = 2; j < cpn; j += 2) { + TPointD p0 = stroke->getControlPoint(j - 2); + TPointD p1 = stroke->getControlPoint(j - 1); + TPointD p2 = stroke->getControlPoint(j); + + TPointD q = p1 - (p0 + p2) * 0.5; + + // Search corner point + if (j > 2) { + tg2 = -p0 + p2 + 2 * q; // Tangent vector to this chunk at t=0 + double prod_scal = + tg2 * tg1; // Inner product between tangent vectors at t=0. + assert(tg1 != TPointD(0, 0) || tg2 != TPointD(0, 0)); + // Compute corner between two tangent vectors + double angolo = + acos(prod_scal / (pow(norm2(tg2), 0.5) * pow(norm2(tg1), 0.5))); + + // Add corner point + if (angolo > angoloLim) { + double w = getWfromChunkAndT(stroke, (UINT)(0.5 * (j - 2)), + 0); // transform lacal t to global t + parameterValues.push_back(w); + } + } + tg1 = -p0 + p2 - 2 * q; // Tangent vector to this chunk at t=1 + + // End search corner point + + // Search max curvature point + // Value of t where the curvature function has got an extreme. + // (Point where first derivate is null) + double estremo_int = 0; + double t = -1; + if (q != TPointD(0, 0)) { + t = 0.25 * (2 * q.x * q.x + 2 * q.y * q.y - q.x * p0.x + q.x * p2.x - + q.y * p0.y + q.y * p2.y) / + (q.x * q.x + q.y * q.y); + + dp = -p0 + p2 + 2 * q - 4 * t * q; // First derivate of the curve + ddp = -4 * q; // Second derivate of the curve + estremo_int = curvature(dp, ddp); + + double h = 0.01; + dp = -p0 + p2 + 2 * q - 4 * (t + h) * q; + double c_dx = curvature(dp, ddp); + dp = -p0 + p2 + 2 * q - 4 * (t - h) * q; + double c_sx = curvature(dp, ddp); + // Check the point is a max and not a minimum + if (estremo_int < c_dx && estremo_int < c_sx) { + estremo_int = 0; + } + } + double curv_max = estremo_int; + + // Compute curvature at the extreme of interval [0,1] + // Compute curvature at t=0 (Left extreme) + dp = -p0 + p2 + 2 * q; + double estremo_sx = curvature(dp, ddp); + + // Compute curvature at t=1 (Right extreme) + dp = -p0 + p2 - 2 * q; + double estremo_dx = curvature(dp, ddp); + + // Compare curvature at the extreme of interval [0,1] with the internal + // value + double t_ext; + if (estremo_sx >= estremo_dx) + t_ext = 0; + else + t_ext = 1; + double maxEstremi = std::max(estremo_dx, estremo_sx); + if (maxEstremi > estremo_int) { + t = t_ext; + curv_max = maxEstremi; + } + + // Add max curvature point + if (t >= 0 && t <= 1 && curv_max > curvMaxLim) { + double w = getWfromChunkAndT(stroke, (UINT)(0.5 * (j - 2)), + t); // transform local t to global t + parameterValues.push_back(w); + } + // End search max curvature point + } + // Delete duplicate of parameterValues + // Because some max cuvature point can coincide with the corner point + if ((int)parameterValues.size() > 1) { + std::sort(parameterValues.begin(), parameterValues.end()); + parameterValues.erase( + std::unique(parameterValues.begin(), parameterValues.end()), + parameterValues.end()); + } +} + +static void addStroke(TTool::Application *application, const TVectorImageP &vi, + TStroke *stroke, bool breakAngles, bool frameCreated, + bool levelCreated, TXshSimpleLevel *sLevel = NULL, + TFrameId fid = TFrameId::NO_FRAME) { + QMutexLocker lock(vi->getMutex()); + + if (application->getCurrentObject()->isSpline()) { + application->getCurrentXsheet()->notifyXsheetChanged(); + return; + } + + std::vector corners; + std::vector strokes; + + const float angoloLim = + 1; // Value (radians) of the Corner between two tangent vector. + // Up this value the two corner can be considered angular. + const float curvMaxLim = 0.8; // Value of the max curvature. + // Up this value the point can be considered a max curvature point. + + findMaxCurvPoints(stroke, angoloLim, curvMaxLim, corners); + TXshSimpleLevel *sl; + if (!sLevel) { + sl = application->getCurrentLevel()->getSimpleLevel(); + } else { + sl = sLevel; + } + TFrameId id = application->getCurrentTool()->getTool()->getCurrentFid(); + if (id == TFrameId::NO_FRAME && fid != TFrameId::NO_FRAME) id = fid; + if (!corners.empty()) { + if (breakAngles) + split(stroke, corners, strokes); + else + strokes.push_back(new TStroke(*stroke)); + + int n = strokes.size(); + + TUndoManager::manager()->beginBlock(); + for (int i = 0; i < n; i++) { + std::vector *fillInformation = + new std::vector; + ImageUtils::getFillingInformationOverlappingArea(vi, *fillInformation, + stroke->getBBox()); + TStroke *str = new TStroke(*strokes[i]); + vi->addStroke(str); + TUndoManager::manager()->add(new UndoPencil(str, fillInformation, sl, id, + frameCreated, levelCreated)); + } + TUndoManager::manager()->endBlock(); + } else { + std::vector *fillInformation = + new std::vector; + ImageUtils::getFillingInformationOverlappingArea(vi, *fillInformation, + stroke->getBBox()); + TStroke *str = new TStroke(*stroke); + vi->addStroke(str); + TUndoManager::manager()->add(new UndoPencil(str, fillInformation, sl, id, + frameCreated, levelCreated)); + } + + // Update regions. It will call roundStroke() in + // TVectorImage::Imp::findIntersections(). + // roundStroke() will slightly modify all the stroke positions. + // It is needed to update information for Fill Check. + vi->findRegions(); + + for (int k = 0; k < (int)strokes.size(); k++) delete strokes[k]; + strokes.clear(); + + application->getCurrentTool()->getTool()->notifyImageChanged(); +} + +//------------------------------------------------------------------- +// +// Gennaro: end +// +//------------------------------------------------------------------- + +//=================================================================== +// +// Helper functions and classes +// +//------------------------------------------------------------------- + +namespace { + +//------------------------------------------------------------------- + +void addStrokeToImage(TTool::Application *application, const TVectorImageP &vi, + TStroke *stroke, bool breakAngles, bool frameCreated, + bool levelCreated, TXshSimpleLevel *sLevel = NULL, + TFrameId id = TFrameId::NO_FRAME) { + QMutexLocker lock(vi->getMutex()); + addStroke(application, vi.getPointer(), stroke, breakAngles, frameCreated, + levelCreated, sLevel, id); + // la notifica viene gia fatta da addStroke! + // getApplication()->getCurrentTool()->getTool()->notifyImageChanged(); +} + +//--------------------------------------------------------------------------------------------------------- + +enum DrawOrder { OverAll = 0, UnderAll, PaletteOrder }; + +void getAboveStyleIdSet(int styleId, TPaletteP palette, + QSet &aboveStyles) { + if (!palette) return; + for (int p = 0; p < palette->getPageCount(); p++) { + TPalette::Page *page = palette->getPage(p); + for (int s = 0; s < page->getStyleCount(); s++) { + int tmpId = page->getStyleId(s); + if (tmpId == styleId) return; + if (tmpId != 0) aboveStyles.insert(tmpId); + } + } +} + +//========================================================================================================= + +class RasterBrushUndo final : public TRasterUndo { + std::vector m_points; + int m_styleId; + bool m_selective; + bool m_isPaletteOrder; + bool m_isPencil; + +public: + RasterBrushUndo(TTileSetCM32 *tileSet, const std::vector &points, + int styleId, bool selective, TXshSimpleLevel *level, + const TFrameId &frameId, bool isPencil, bool isFrameCreated, + bool isLevelCreated, bool isPaletteOrder) + : TRasterUndo(tileSet, level, frameId, isFrameCreated, isLevelCreated, 0) + , m_points(points) + , m_styleId(styleId) + , m_selective(selective) + , m_isPencil(isPencil) + , m_isPaletteOrder(isPaletteOrder) {} + + void redo() const override { + insertLevelAndFrameIfNeeded(); + TToonzImageP image = getImage(); + TRasterCM32P ras = image->getRaster(); + RasterStrokeGenerator m_rasterTrack(ras, BRUSH, NONE, m_styleId, + m_points[0], m_selective, 0, + !m_isPencil, m_isPaletteOrder); + if (m_isPaletteOrder) { + QSet aboveStyleIds; + getAboveStyleIdSet(m_styleId, image->getPalette(), aboveStyleIds); + m_rasterTrack.setAboveStyleIds(aboveStyleIds); + } + m_rasterTrack.setPointsSequence(m_points); + m_rasterTrack.generateStroke(m_isPencil); + image->setSavebox(image->getSavebox() + + m_rasterTrack.getBBox(m_rasterTrack.getPointsSequence())); + ToolUtils::updateSaveBox(); + TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); + notifyImageChanged(); + } + + int getSize() const override { + return sizeof(*this) + TRasterUndo::getSize(); + } + QString getToolName() override { return QString("Brush Tool"); } + int getHistoryType() override { return HistoryType::BrushTool; } +}; + +//========================================================================================================= + +class RasterBluredBrushUndo final : public TRasterUndo { + std::vector m_points; + int m_styleId; + DrawOrder m_drawOrder; + int m_maxThick; + double m_hardness; + +public: + RasterBluredBrushUndo(TTileSetCM32 *tileSet, + const std::vector &points, int styleId, + DrawOrder drawOrder, TXshSimpleLevel *level, + const TFrameId &frameId, int maxThick, double hardness, + bool isFrameCreated, bool isLevelCreated) + : TRasterUndo(tileSet, level, frameId, isFrameCreated, isLevelCreated, 0) + , m_points(points) + , m_styleId(styleId) + , m_drawOrder(drawOrder) + , m_maxThick(maxThick) + , m_hardness(hardness) {} + + void redo() const override { + if (m_points.size() == 0) return; + insertLevelAndFrameIfNeeded(); + TToonzImageP image = getImage(); + TRasterCM32P ras = image->getRaster(); + TRasterCM32P backupRas = ras->clone(); + TRaster32P workRaster(ras->getSize()); + QRadialGradient brushPad = ToolUtils::getBrushPad(m_maxThick, m_hardness); + workRaster->clear(); + BluredBrush brush(workRaster, m_maxThick, brushPad, false); + + if (m_drawOrder == PaletteOrder) { + QSet aboveStyleIds; + getAboveStyleIdSet(m_styleId, image->getPalette(), aboveStyleIds); + brush.setAboveStyleIds(aboveStyleIds); + } + + std::vector points; + points.push_back(m_points[0]); + TRect bbox = brush.getBoundFromPoints(points); + brush.addPoint(m_points[0], 1); + brush.updateDrawing(ras, ras, bbox, m_styleId, (int)m_drawOrder); + if (m_points.size() > 1) { + points.clear(); + points.push_back(m_points[0]); + points.push_back(m_points[1]); + bbox = brush.getBoundFromPoints(points); + brush.addArc(m_points[0], (m_points[1] + m_points[0]) * 0.5, m_points[1], + 1, 1); + brush.updateDrawing(ras, backupRas, bbox, m_styleId, (int)m_drawOrder); + int i; + for (i = 1; i + 2 < (int)m_points.size(); i = i + 2) { + points.clear(); + points.push_back(m_points[i]); + points.push_back(m_points[i + 1]); + points.push_back(m_points[i + 2]); + bbox = brush.getBoundFromPoints(points); + brush.addArc(m_points[i], m_points[i + 1], m_points[i + 2], 1, 1); + brush.updateDrawing(ras, backupRas, bbox, m_styleId, (int)m_drawOrder); + } + } + ToolUtils::updateSaveBox(); + TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); + notifyImageChanged(); + } + + int getSize() const override { + return sizeof(*this) + TRasterUndo::getSize(); + } + + QString getToolName() override { return QString("Brush Tool"); } + int getHistoryType() override { return HistoryType::BrushTool; } +}; + +//========================================================================================================= + +class MyPaintBrushUndo final : public TRasterUndo { + TPoint m_offset; + QString m_id; + +public: + MyPaintBrushUndo(TTileSetCM32 *tileSet, TXshSimpleLevel *level, + const TFrameId &frameId, bool isFrameCreated, + bool isLevelCreated, const TRasterCM32P &ras, + const TPoint &offset) + : TRasterUndo(tileSet, level, frameId, isFrameCreated, isLevelCreated, 0) + , m_offset(offset) { + static int counter = 0; + m_id = QString("MyPaintBrushUndo") + QString::number(counter++); + TImageCache::instance()->add(m_id.toStdString(), + TToonzImageP(ras, TRect(ras->getSize()))); + } + + ~MyPaintBrushUndo() { TImageCache::instance()->remove(m_id); } + + void redo() const override { + insertLevelAndFrameIfNeeded(); + + TToonzImageP image = getImage(); + TRasterCM32P ras = image->getRaster(); + + TImageP srcImg = + TImageCache::instance()->get(m_id.toStdString(), false)->cloneImage(); + TToonzImageP tSrcImg = srcImg; + assert(tSrcImg); + ras->copy(tSrcImg->getRaster(), m_offset); + ToolUtils::updateSaveBox(); + TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); + notifyImageChanged(); + } + + int getSize() const override { + return sizeof(*this) + TRasterUndo::getSize(); + } + + QString getToolName() override { return QString("Brush Tool"); } + int getHistoryType() override { return HistoryType::BrushTool; } +}; + +//========================================================================================================= + +double computeThickness(double pressure, const TDoublePairProperty &property) { + double t = pressure * pressure * pressure; + double thick0 = property.getValue().first; + double thick1 = property.getValue().second; + if (thick1 < 0.0001) thick0 = thick1 = 0.0; + return (thick0 + (thick1 - thick0) * t) * 0.5; +} + +//--------------------------------------------------------------------------------------------------------- + +int computeThickness(double pressure, const TIntPairProperty &property) { + double t = pressure * pressure * pressure; + int thick0 = property.getValue().first; + int thick1 = property.getValue().second; + return tround(thick0 + (thick1 - thick0) * t); +} + +} // namespace + +//-------------------------------------------------------------------------------------------------- + +static void CatmullRomInterpolate(const TThickPoint &P0, const TThickPoint &P1, + const TThickPoint &P2, const TThickPoint &P3, + int samples, + std::vector &points) { + double x0 = P1.x; + double x1 = (-P0.x + P2.x) * 0.5f; + double x2 = P0.x - 2.5f * P1.x + 2.0f * P2.x - 0.5f * P3.x; + double x3 = -0.5f * P0.x + 1.5f * P1.x - 1.5f * P2.x + 0.5f * P3.x; + + double y0 = P1.y; + double y1 = (-P0.y + P2.y) * 0.5f; + double y2 = P0.y - 2.5f * P1.y + 2.0f * P2.y - 0.5f * P3.y; + double y3 = -0.5f * P0.y + 1.5f * P1.y - 1.5f * P2.y + 0.5f * P3.y; + + double z0 = P1.thick; + double z1 = (-P0.thick + P2.thick) * 0.5f; + double z2 = P0.thick - 2.5f * P1.thick + 2.0f * P2.thick - 0.5f * P3.thick; + double z3 = + -0.5f * P0.thick + 1.5f * P1.thick - 1.5f * P2.thick + 0.5f * P3.thick; + + for (int i = 1; i <= samples; ++i) { + double t = i / (double)(samples + 1); + double t2 = t * t; + double t3 = t2 * t; + TThickPoint p; + p.x = x0 + x1 * t + x2 * t2 + x3 * t3; + p.y = y0 + y1 * t + y2 * t2 + y3 * t3; + p.thick = z0 + z1 * t + z2 * t2 + z3 * t3; + points.push_back(p); + } +} + +//-------------------------------------------------------------------------------------------------- + +static void Smooth(std::vector &points, int radius) { + int n = (int)points.size(); + if (radius < 1 || n < 3) { + return; + } + + std::vector result; + + float d = 1.0f / (radius * 2 + 1); + + for (int i = 1; i < n - 1; ++i) { + int lower = i - radius; + int upper = i + radius; + + TThickPoint total; + total.x = 0; + total.y = 0; + total.thick = 0; + + for (int j = lower; j <= upper; ++j) { + int idx = j; + if (idx < 0) { + idx = 0; + } else if (idx >= n) { + idx = n - 1; + } + total.x += points[idx].x; + total.y += points[idx].y; + total.thick += points[idx].thick; + } + + total.x *= d; + total.y *= d; + total.thick *= d; + result.push_back(total); + } + + for (int i = 1; i < n - 1; ++i) { + points[i].x = result[i - 1].x; + points[i].y = result[i - 1].y; + points[i].thick = result[i - 1].thick; + } + + if (points.size() >= 3) { + std::vector pts; + CatmullRomInterpolate(points[0], points[0], points[1], points[2], 10, pts); + std::vector::iterator it = points.begin(); + points.insert(it, pts.begin(), pts.end()); + + pts.clear(); + CatmullRomInterpolate(points[n - 3], points[n - 2], points[n - 1], + points[n - 1], 10, pts); + it = points.begin(); + it += n - 1; + points.insert(it, pts.begin(), pts.end()); + } +} + +//-------------------------------------------------------------------------------------------------- + +void SmoothStroke::beginStroke(int smooth) { + m_smooth = smooth; + m_outputIndex = 0; + m_readIndex = -1; + m_rawPoints.clear(); + m_outputPoints.clear(); +} + +//-------------------------------------------------------------------------------------------------- + +void SmoothStroke::addPoint(const TThickPoint &point) { + if (m_rawPoints.size() > 0 && m_rawPoints.back().x == point.x && + m_rawPoints.back().y == point.y) { + return; + } + m_rawPoints.push_back(point); + generatePoints(); +} + +//-------------------------------------------------------------------------------------------------- + +void SmoothStroke::endStroke() { + generatePoints(); + // force enable the output all segments + m_outputIndex = m_outputPoints.size() - 1; +} + +//-------------------------------------------------------------------------------------------------- + +void SmoothStroke::clearPoints() { + m_outputIndex = 0; + m_readIndex = -1; + m_outputPoints.clear(); + m_rawPoints.clear(); +} + +//-------------------------------------------------------------------------------------------------- + +void SmoothStroke::getSmoothPoints(std::vector &smoothPoints) { + int n = m_outputPoints.size(); + for (int i = m_readIndex + 1; i <= m_outputIndex && i < n; ++i) { + smoothPoints.push_back(m_outputPoints[i]); + } + m_readIndex = m_outputIndex; +} + +//-------------------------------------------------------------------------------------------------- + +void SmoothStroke::generatePoints() { + int n = (int)m_rawPoints.size(); + if (n == 0) { + return; + } + + // if m_smooth = 0, then skip whole smoothing process + if (m_smooth == 0) { + for (int i = m_outputIndex; i < (int)m_outputPoints.size(); ++i) { + if (m_outputPoints[i] != m_rawPoints[i]) { + break; + } + ++m_outputIndex; + } + m_outputPoints = m_rawPoints; + return; + } + + std::vector smoothedPoints; + // Add more stroke samples before applying the smoothing + // This is because the raw inputs points are too few to support smooth result, + // especially on stroke ends + smoothedPoints.push_back(m_rawPoints.front()); + for (int i = 1; i < n; ++i) { + const TThickPoint &p1 = m_rawPoints[i - 1]; + const TThickPoint &p2 = m_rawPoints[i]; + const TThickPoint &p0 = i - 2 >= 0 ? m_rawPoints[i - 2] : p1; + const TThickPoint &p3 = i + 1 < n ? m_rawPoints[i + 1] : p2; + + int samples = 8; + CatmullRomInterpolate(p0, p1, p2, p3, samples, smoothedPoints); + smoothedPoints.push_back(p2); + } + // Apply the 1D box filter + // Multiple passes result in better quality and fix the stroke ends break + // issue + for (int i = 0; i < 3; ++i) { + Smooth(smoothedPoints, m_smooth); + } + // Compare the new smoothed stroke with old one + // Enable the output for unchanged parts + int outputNum = (int)m_outputPoints.size(); + for (int i = m_outputIndex; i < outputNum; ++i) { + if (m_outputPoints[i] != smoothedPoints[i]) { + break; + } + ++m_outputIndex; + } + m_outputPoints = smoothedPoints; +} + +//=================================================================== +// +// ToonzRasterBrushTool +// +//----------------------------------------------------------------------------- + +ToonzRasterBrushTool::ToonzRasterBrushTool(std::string name, int targetType) + : TTool(name) + , m_rasThickness("Size", 1, 100, 1, 5) + , m_smooth("Smooth:", 0, 50, 0) + , m_hardness("Hardness:", 0, 100, 100) + , m_preset("Preset:") + , m_drawOrder("Draw Order:") + , m_pencil("Pencil", false) + , m_pressure("Pressure", true) + , m_modifierSize("ModifierSize", -3, 3, 0, true) + , m_rasterTrack(0) + , m_styleId(0) + , m_bluredBrush(0) + , m_active(false) + , m_enabled(false) + , m_isPrompting(false) + , m_firstTime(true) + , m_presetsLoaded(false) + , m_targetType(targetType) + , m_workingFrameId(TFrameId()) + , m_notifier(0) { + bind(targetType); + + m_prop[0].bind(m_rasThickness); + m_prop[0].bind(m_hardness); + m_prop[0].bind(m_smooth); + m_prop[0].bind(m_drawOrder); + m_prop[0].bind(m_modifierSize); + m_prop[0].bind(m_pencil); + m_pencil.setId("PencilMode"); + + m_drawOrder.addValue(L"Over All"); + m_drawOrder.addValue(L"Under All"); + m_drawOrder.addValue(L"Palette Order"); + m_drawOrder.setId("DrawOrder"); + + m_prop[0].bind(m_pressure); + + m_prop[0].bind(m_preset); + m_preset.setId("BrushPreset"); + m_preset.addValue(CUSTOM_WSTR); + m_pressure.setId("PressureSensitivity"); +} + +//------------------------------------------------------------------------------------------------------- + +ToolOptionsBox *ToonzRasterBrushTool::createOptionsBox() { + TPaletteHandle *currPalette = + TTool::getApplication()->getPaletteController()->getCurrentLevelPalette(); + ToolHandle *currTool = TTool::getApplication()->getCurrentTool(); + return new BrushToolOptionsBox(0, this, currPalette, currTool); +} + +//------------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::drawLine(const TPointD &point, const TPointD ¢re, + bool horizontal, bool isDecimal) { + if (!isDecimal) { + if (horizontal) { + tglDrawSegment(TPointD(point.x - 1.5, point.y + 0.5) + centre, + TPointD(point.x - 0.5, point.y + 0.5) + centre); + tglDrawSegment(TPointD(point.y - 0.5, -point.x + 1.5) + centre, + TPointD(point.y - 0.5, -point.x + 0.5) + centre); + tglDrawSegment(TPointD(-point.x + 0.5, -point.y + 0.5) + centre, + TPointD(-point.x - 0.5, -point.y + 0.5) + centre); + tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre, + TPointD(-point.y - 0.5, point.x + 0.5) + centre); + + tglDrawSegment(TPointD(point.y - 0.5, point.x + 0.5) + centre, + TPointD(point.y - 0.5, point.x - 0.5) + centre); + tglDrawSegment(TPointD(point.x - 0.5, -point.y + 0.5) + centre, + TPointD(point.x - 1.5, -point.y + 0.5) + centre); + tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre, + TPointD(-point.y - 0.5, -point.x + 1.5) + centre); + tglDrawSegment(TPointD(-point.x - 0.5, point.y + 0.5) + centre, + TPointD(-point.x + 0.5, point.y + 0.5) + centre); + } else { + tglDrawSegment(TPointD(point.x - 1.5, point.y + 1.5) + centre, + TPointD(point.x - 1.5, point.y + 0.5) + centre); + tglDrawSegment(TPointD(point.x - 1.5, point.y + 0.5) + centre, + TPointD(point.x - 0.5, point.y + 0.5) + centre); + tglDrawSegment(TPointD(point.y + 0.5, -point.x + 1.5) + centre, + TPointD(point.y - 0.5, -point.x + 1.5) + centre); + tglDrawSegment(TPointD(point.y - 0.5, -point.x + 1.5) + centre, + TPointD(point.y - 0.5, -point.x + 0.5) + centre); + tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 0.5) + centre, + TPointD(-point.x + 0.5, -point.y + 0.5) + centre); + tglDrawSegment(TPointD(-point.x + 0.5, -point.y + 0.5) + centre, + TPointD(-point.x - 0.5, -point.y + 0.5) + centre); + tglDrawSegment(TPointD(-point.y - 1.5, point.x - 0.5) + centre, + TPointD(-point.y - 0.5, point.x - 0.5) + centre); + tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre, + TPointD(-point.y - 0.5, point.x + 0.5) + centre); + + tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre, + TPointD(point.y - 0.5, point.x - 0.5) + centre); + tglDrawSegment(TPointD(point.y - 0.5, point.x - 0.5) + centre, + TPointD(point.y - 0.5, point.x + 0.5) + centre); + tglDrawSegment(TPointD(point.x - 1.5, -point.y - 0.5) + centre, + TPointD(point.x - 1.5, -point.y + 0.5) + centre); + tglDrawSegment(TPointD(point.x - 1.5, -point.y + 0.5) + centre, + TPointD(point.x - 0.5, -point.y + 0.5) + centre); + tglDrawSegment(TPointD(-point.y - 1.5, -point.x + 1.5) + centre, + TPointD(-point.y - 0.5, -point.x + 1.5) + centre); + tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 1.5) + centre, + TPointD(-point.y - 0.5, -point.x + 0.5) + centre); + tglDrawSegment(TPointD(-point.x + 0.5, point.y + 1.5) + centre, + TPointD(-point.x + 0.5, point.y + 0.5) + centre); + tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre, + TPointD(-point.x - 0.5, point.y + 0.5) + centre); + } + } else { + if (horizontal) { + tglDrawSegment(TPointD(point.x - 0.5, point.y + 0.5) + centre, + TPointD(point.x + 0.5, point.y + 0.5) + centre); + tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre, + TPointD(point.y + 0.5, point.x + 0.5) + centre); + tglDrawSegment(TPointD(point.y + 0.5, -point.x + 0.5) + centre, + TPointD(point.y + 0.5, -point.x - 0.5) + centre); + tglDrawSegment(TPointD(point.x + 0.5, -point.y - 0.5) + centre, + TPointD(point.x - 0.5, -point.y - 0.5) + centre); + tglDrawSegment(TPointD(-point.x - 0.5, -point.y - 0.5) + centre, + TPointD(-point.x + 0.5, -point.y - 0.5) + centre); + tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre, + TPointD(-point.y - 0.5, -point.x - 0.5) + centre); + tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre, + TPointD(-point.y - 0.5, point.x + 0.5) + centre); + tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre, + TPointD(-point.x - 0.5, point.y + 0.5) + centre); + } else { + tglDrawSegment(TPointD(point.x - 0.5, point.y + 1.5) + centre, + TPointD(point.x - 0.5, point.y + 0.5) + centre); + tglDrawSegment(TPointD(point.x - 0.5, point.y + 0.5) + centre, + TPointD(point.x + 0.5, point.y + 0.5) + centre); + tglDrawSegment(TPointD(point.y + 1.5, point.x - 0.5) + centre, + TPointD(point.y + 0.5, point.x - 0.5) + centre); + tglDrawSegment(TPointD(point.y + 0.5, point.x - 0.5) + centre, + TPointD(point.y + 0.5, point.x + 0.5) + centre); + tglDrawSegment(TPointD(point.y + 1.5, -point.x + 0.5) + centre, + TPointD(point.y + 0.5, -point.x + 0.5) + centre); + tglDrawSegment(TPointD(point.y + 0.5, -point.x + 0.5) + centre, + TPointD(point.y + 0.5, -point.x - 0.5) + centre); + tglDrawSegment(TPointD(point.x - 0.5, -point.y - 1.5) + centre, + TPointD(point.x - 0.5, -point.y - 0.5) + centre); + tglDrawSegment(TPointD(point.x - 0.5, -point.y - 0.5) + centre, + TPointD(point.x + 0.5, -point.y - 0.5) + centre); + + tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 1.5) + centre, + TPointD(-point.x + 0.5, -point.y - 0.5) + centre); + tglDrawSegment(TPointD(-point.x + 0.5, -point.y - 0.5) + centre, + TPointD(-point.x - 0.5, -point.y - 0.5) + centre); + tglDrawSegment(TPointD(-point.y - 1.5, -point.x + 0.5) + centre, + TPointD(-point.y - 0.5, -point.x + 0.5) + centre); + tglDrawSegment(TPointD(-point.y - 0.5, -point.x + 0.5) + centre, + TPointD(-point.y - 0.5, -point.x - 0.5) + centre); + tglDrawSegment(TPointD(-point.y - 1.5, point.x - 0.5) + centre, + TPointD(-point.y - 0.5, point.x - 0.5) + centre); + tglDrawSegment(TPointD(-point.y - 0.5, point.x - 0.5) + centre, + TPointD(-point.y - 0.5, point.x + 0.5) + centre); + tglDrawSegment(TPointD(-point.x + 0.5, point.y + 1.5) + centre, + TPointD(-point.x + 0.5, point.y + 0.5) + centre); + tglDrawSegment(TPointD(-point.x + 0.5, point.y + 0.5) + centre, + TPointD(-point.x - 0.5, point.y + 0.5) + centre); + } + } +} + +//------------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::drawEmptyCircle(TPointD pos, int thick, + bool isLxEven, bool isLyEven, + bool isPencil) { + if (isLxEven) pos.x += 0.5; + if (isLyEven) pos.y += 0.5; + + if (!isPencil) + tglDrawCircle(pos, (thick + 1) * 0.5); + else { + int x = 0, y = tround((thick * 0.5) - 0.5); + int d = 3 - 2 * (int)(thick * 0.5); + bool horizontal = true, isDecimal = thick % 2 != 0; + drawLine(TPointD(x, y), pos, horizontal, isDecimal); + while (y > x) { + if (d < 0) { + d = d + 4 * x + 6; + horizontal = true; + } else { + d = d + 4 * (x - y) + 10; + horizontal = false; + y--; + } + x++; + drawLine(TPointD(x, y), pos, horizontal, isDecimal); + } + } +} + +//------------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::updateTranslation() { + m_rasThickness.setQStringName(tr("Size")); + m_hardness.setQStringName(tr("Hardness:")); + m_smooth.setQStringName(tr("Smooth:")); + m_drawOrder.setQStringName(tr("Draw Order:")); + m_drawOrder.setItemUIName(L"Over All", tr("Over All")); + m_drawOrder.setItemUIName(L"Under All", tr("Under All")); + m_drawOrder.setItemUIName(L"Palette Order", tr("Palette Order")); + m_modifierSize.setQStringName(tr("Size")); + + // m_filled.setQStringName(tr("Filled")); + m_preset.setQStringName(tr("Preset:")); + m_preset.setItemUIName(CUSTOM_WSTR, tr("")); + m_pencil.setQStringName(tr("Pencil")); + m_pressure.setQStringName(tr("Pressure")); +} + +//--------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::updateWorkAndBackupRasters(const TRect &rect) { + TToonzImageP ti = TImageP(getImage(false, 1)); + if (!ti) return; + + TRasterCM32P ras = ti->getRaster(); + + if (m_isMyPaintStyleSelected) { + const int denominator = 8; + TRect enlargedRect = rect + m_lastRect; + int dx = (enlargedRect.getLx() - 1) / denominator + 1; + int dy = (enlargedRect.getLy() - 1) / denominator + 1; + + if (m_lastRect.isEmpty()) { + enlargedRect.x0 -= dx; + enlargedRect.y0 -= dy; + enlargedRect.x1 += dx; + enlargedRect.y1 += dy; + + TRect _rect = enlargedRect * ras->getBounds(); + if (_rect.isEmpty()) return; + + m_workRas->extract(_rect)->copy(ras->extract(_rect)); + m_backupRas->extract(_rect)->copy(ras->extract(_rect)); + } else { + if (enlargedRect.x0 < m_lastRect.x0) enlargedRect.x0 -= dx; + if (enlargedRect.y0 < m_lastRect.y0) enlargedRect.y0 -= dy; + if (enlargedRect.x1 > m_lastRect.x1) enlargedRect.x1 += dx; + if (enlargedRect.y1 > m_lastRect.y1) enlargedRect.y1 += dy; + + TRect _rect = enlargedRect * ras->getBounds(); + if (_rect.isEmpty()) return; + + TRect _lastRect = m_lastRect * ras->getBounds(); + QList rects = ToolUtils::splitRect(_rect, _lastRect); + for (int i = 0; i < rects.size(); i++) { + m_workRas->extract(rects[i])->copy(ras->extract(rects[i])); + m_backupRas->extract(rects[i])->copy(ras->extract(rects[i])); + } + } + + m_lastRect = enlargedRect; + return; + } + + TRect _rect = rect * ras->getBounds(); + TRect _lastRect = m_lastRect * ras->getBounds(); + + if (_rect.isEmpty()) return; + + if (m_lastRect.isEmpty()) { + m_workRas->extract(_rect)->clear(); + m_backupRas->extract(_rect)->copy(ras->extract(_rect)); + return; + } + + QList rects = ToolUtils::splitRect(_rect, _lastRect); + for (int i = 0; i < rects.size(); i++) { + m_workRas->extract(rects[i])->clear(); + m_backupRas->extract(rects[i])->copy(ras->extract(rects[i])); + } +} + +//--------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::onActivate() { + if (!m_notifier) m_notifier = new ToonzRasterBrushToolNotifier(this); + + if (m_firstTime) { + m_rasThickness.setValue( + TDoublePairProperty::Value(RasterBrushMinSize, RasterBrushMaxSize)); + + m_drawOrder.setIndex(BrushDrawOrder); + m_pencil.setValue(RasterBrushPencilMode ? 1 : 0); + m_hardness.setValue(RasterBrushHardness); + + m_pressure.setValue(BrushPressureSensitivity ? 1 : 0); + m_firstTime = false; + m_smooth.setValue(BrushSmooth); + m_modifierSize.setValue(RasterBrushModifierSize); + } + m_brushPad = ToolUtils::getBrushPad(m_rasThickness.getValue().second, + m_hardness.getValue() * 0.01); + setWorkAndBackupImages(); + + m_brushTimer.start(); + // TODO:app->editImageOrSpline(); +} + +//-------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::onDeactivate() { + /*--- + * ドラッグ中にツールが切り替わった場合に備え、onDeactivateにもMouseReleaseと同じ処理を行う + * ---*/ + if (m_tileSaver) { + bool isValid = m_enabled && m_active; + m_enabled = false; + if (isValid) { + finishRasterBrush(m_mousePos, + 1); /*-- 最後のストロークの筆圧は1とする --*/ + } + } + m_workRas = TRaster32P(); + m_backupRas = TRasterCM32P(); +} + +//-------------------------------------------------------------------------------------------------- + +bool ToonzRasterBrushTool::askRead(const TRect &rect) { return askWrite(rect); } + +//-------------------------------------------------------------------------------------------------- + +bool ToonzRasterBrushTool::askWrite(const TRect &rect) { + if (rect.isEmpty()) return true; + m_strokeRect += rect; + m_strokeSegmentRect += rect; + updateWorkAndBackupRasters(rect); + m_tileSaver->save(rect); + return true; +} + +//-------------------------------------------------------------------------------------------------- + +bool ToonzRasterBrushTool::preLeftButtonDown() { + touchImage(); + if (m_isFrameCreated) { + setWorkAndBackupImages(); + // When the xsheet frame is selected, whole viewer will be updated from + // SceneViewer::onXsheetChanged() on adding a new frame. + // We need to take care of a case when the level frame is selected. + if (m_application->getCurrentFrame()->isEditingLevel()) invalidate(); + } + return true; +} + +//-------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos, + const TMouseEvent &e) { + TTool::Application *app = TTool::getApplication(); + if (!app) return; + + int col = app->getCurrentColumn()->getColumnIndex(); + m_enabled = col >= 0; + // todo: gestire autoenable + if (!m_enabled) return; + + m_currentColor = TPixel32::Black; + m_active = !!getImage(true); + if (!m_active) { + m_active = !!touchImage(); + } + if (!m_active) return; + + if (m_active) { + // nel caso che il colore corrente sia un cleanup/studiopalette color + // oppure il colore di un colorfield + m_styleId = app->getCurrentLevelStyleIndex(); + TColorStyle *cs = app->getCurrentLevelStyle(); + if (cs) { + TRasterStyleFx *rfx = cs ? cs->getRasterStyleFx() : 0; + m_active = cs != 0 && (cs->isStrokeStyle() || (rfx && rfx->isInkStyle())); + m_currentColor = cs->getAverageColor(); + m_currentColor.m = 255; + } else { + m_styleId = 1; + m_currentColor = TPixel32::Black; + } + } + + // assert(0<=m_styleId && m_styleId<2); + TImageP img = getImage(true); + TToonzImageP ri(img); + TRasterCM32P ras = ri->getRaster(); + if (ras) { + TPointD rasCenter = ras->getCenterD(); + m_tileSet = new TTileSetCM32(ras->getSize()); + m_tileSaver = new TTileSaverCM32(ras, m_tileSet); + double maxThick = m_rasThickness.getValue().second; + double thickness = (m_pressure.getValue()) + ? computeThickness(e.m_pressure, m_rasThickness) * 2 + : maxThick; + + /*--- ストロークの最初にMaxサイズの円が描かれてしまう不具合を防止する + * ---*/ + if (m_pressure.getValue() && e.m_pressure == 1.0) + thickness = m_rasThickness.getValue().first; + + TPointD halfThick(maxThick * 0.5, maxThick * 0.5); + TRectD invalidateRect(pos - halfThick, pos + halfThick); + TPointD dpi; + ri->getDpi(dpi.x, dpi.y); + TRectD previousTipRect(m_brushPos - halfThick, m_brushPos + halfThick); + if (dpi.x > Stage::inch || dpi.y > Stage::inch) + previousTipRect *= dpi.x / Stage::inch; + invalidateRect += previousTipRect; + + // if the drawOrder mode = "Palette Order", + // get styleId list which is above the current style in the palette + DrawOrder drawOrder = (DrawOrder)m_drawOrder.getIndex(); + QSet aboveStyleIds; + if (drawOrder == PaletteOrder) { + getAboveStyleIdSet(m_styleId, ri->getPalette(), aboveStyleIds); + } + + // mypaint brush case + if (m_isMyPaintStyleSelected) { + TPointD point(pos + rasCenter); + double pressure = + m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5; + updateCurrentStyle(); + if (!(m_workRas && m_backupRas)) setWorkAndBackupImages(); + m_workRas->lock(); + mypaint::Brush mypaintBrush; + TMyPaintBrushStyle *mypaintStyle = + dynamic_cast(app->getCurrentLevelStyle()); + { // applyToonzBrushSettings + mypaintBrush.fromBrush(mypaintStyle->getBrush()); + double modifierSize = m_modifierSize.getValue() * log(2.0); + float baseSize = + mypaintBrush.getBaseValue(MYPAINT_BRUSH_SETTING_RADIUS_LOGARITHMIC); + mypaintBrush.setBaseValue(MYPAINT_BRUSH_SETTING_RADIUS_LOGARITHMIC, + baseSize + modifierSize); + } + m_toonz_brush = new MyPaintToonzBrush(m_workRas, *this, mypaintBrush); + m_strokeRect.empty(); + m_strokeSegmentRect.empty(); + m_toonz_brush->beginStroke(); + m_toonz_brush->strokeTo(point, pressure, restartBrushTimer()); + TRect updateRect = m_strokeSegmentRect * ras->getBounds(); + if (!updateRect.isEmpty()) { + // ras->extract(updateRect)->copy(m_workRas->extract(updateRect)); + m_toonz_brush->updateDrawing(ri->getRaster(), m_backupRas, m_strokeRect, + m_styleId); + } + m_lastRect = m_strokeRect; + + TPointD thickOffset(m_maxCursorThick * 0.5, m_maxCursorThick * 0.5); + invalidateRect = convert(m_strokeSegmentRect) - rasCenter; + invalidateRect += TRectD(pos - thickOffset, pos + thickOffset); + invalidateRect += + TRectD(m_brushPos - thickOffset, m_brushPos + thickOffset); + } else if (m_hardness.getValue() == 100 || m_pencil.getValue()) { + /*-- Pencilモードでなく、Hardness=100 の場合のブラシサイズを1段階下げる + * --*/ + if (!m_pencil.getValue()) thickness -= 1.0; + + TThickPoint thickPoint(pos + convert(ras->getCenter()), thickness); + m_rasterTrack = new RasterStrokeGenerator( + ras, BRUSH, NONE, m_styleId, thickPoint, drawOrder != OverAll, 0, + !m_pencil.getValue(), drawOrder == PaletteOrder); + + if (drawOrder == PaletteOrder) + m_rasterTrack->setAboveStyleIds(aboveStyleIds); + + m_tileSaver->save(m_rasterTrack->getLastRect()); + m_rasterTrack->generateLastPieceOfStroke(m_pencil.getValue()); + + std::vector pts; + if (m_smooth.getValue() == 0) { + pts.push_back(thickPoint); + } else { + m_smoothStroke.beginStroke(m_smooth.getValue()); + m_smoothStroke.addPoint(thickPoint); + m_smoothStroke.getSmoothPoints(pts); + } + } else { + m_points.clear(); + TThickPoint point(pos + rasCenter, thickness); + m_points.push_back(point); + m_bluredBrush = new BluredBrush(m_workRas, maxThick, m_brushPad, false); + + if (drawOrder == PaletteOrder) + m_bluredBrush->setAboveStyleIds(aboveStyleIds); + + m_strokeRect = m_bluredBrush->getBoundFromPoints(m_points); + updateWorkAndBackupRasters(m_strokeRect); + m_tileSaver->save(m_strokeRect); + m_bluredBrush->addPoint(point, 1); + m_bluredBrush->updateDrawing(ri->getRaster(), m_backupRas, m_strokeRect, + m_styleId, drawOrder); + m_lastRect = m_strokeRect; + + std::vector pts; + if (m_smooth.getValue() == 0) { + pts.push_back(point); + } else { + m_smoothStroke.beginStroke(m_smooth.getValue()); + m_smoothStroke.addPoint(point); + m_smoothStroke.getSmoothPoints(pts); + } + } + /*-- 作業中のFidを登録 --*/ + m_workingFrameId = getFrameId(); + + invalidate(invalidateRect.enlarge(2)); + } + // updating m_brushPos is needed to refresh viewer properly + m_brushPos = m_mousePos = pos; +} + +//------------------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos, + const TMouseEvent &e) { + if (!m_enabled || !m_active) { + m_brushPos = m_mousePos = pos; + return; + } + + TToonzImageP ti = TImageP(getImage(true)); + TPointD rasCenter = ti->getRaster()->getCenterD(); + int maxThickness = m_rasThickness.getValue().second; + double thickness = (m_pressure.getValue()) + ? computeThickness(e.m_pressure, m_rasThickness) * 2 + : maxThickness; + TRectD invalidateRect; + if (m_isMyPaintStyleSelected) { + TRasterP ras = ti->getRaster(); + TPointD point(pos + rasCenter); + double pressure = + m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5; + + m_strokeSegmentRect.empty(); + m_toonz_brush->strokeTo(point, pressure, restartBrushTimer()); + TRect updateRect = m_strokeSegmentRect * ras->getBounds(); + if (!updateRect.isEmpty()) { + // ras->extract(updateRect)->copy(m_workRaster->extract(updateRect)); + m_toonz_brush->updateDrawing(ras, m_backupRas, m_strokeSegmentRect, + m_styleId); + } + m_lastRect = m_strokeRect; + + TPointD thickOffset(m_maxCursorThick * 0.5, m_maxCursorThick * 0.5); + invalidateRect = convert(m_strokeSegmentRect) - rasCenter; + invalidateRect += TRectD(pos - thickOffset, pos + thickOffset); + invalidateRect += + TRectD(m_brushPos - thickOffset, m_brushPos + thickOffset); + } else if (m_rasterTrack && + (m_hardness.getValue() == 100 || m_pencil.getValue())) { + /*-- Pencilモードでなく、Hardness=100 の場合のブラシサイズを1段階下げる + * --*/ + if (!m_pencil.getValue()) thickness -= 1.0; + + TThickPoint thickPoint(pos + rasCenter, thickness); + std::vector pts; + if (m_smooth.getValue() == 0) { + pts.push_back(thickPoint); + } else { + m_smoothStroke.addPoint(thickPoint); + m_smoothStroke.getSmoothPoints(pts); + } + for (size_t i = 0; i < pts.size(); ++i) { + const TThickPoint &thickPoint = pts[i]; + m_rasterTrack->add(thickPoint); + m_tileSaver->save(m_rasterTrack->getLastRect()); + m_rasterTrack->generateLastPieceOfStroke(m_pencil.getValue()); + std::vector brushPoints = m_rasterTrack->getPointsSequence(); + int m = (int)brushPoints.size(); + std::vector points; + if (m == 3) { + points.push_back(brushPoints[0]); + points.push_back(brushPoints[1]); + } else { + points.push_back(brushPoints[m - 4]); + points.push_back(brushPoints[m - 3]); + points.push_back(brushPoints[m - 2]); + } + invalidateRect += ToolUtils::getBounds(points, maxThickness) - rasCenter; + } + } else { + // antialiased brush + assert(m_workRas.getPointer() && m_backupRas.getPointer()); + TThickPoint thickPoint(pos + rasCenter, thickness); + std::vector pts; + if (m_smooth.getValue() == 0) { + pts.push_back(thickPoint); + } else { + m_smoothStroke.addPoint(thickPoint); + m_smoothStroke.getSmoothPoints(pts); + } + for (size_t i = 0; i < pts.size(); ++i) { + TThickPoint old = m_points.back(); + + const TThickPoint &point = pts[i]; + TThickPoint mid((old + point) * 0.5, (point.thick + old.thick) * 0.5); + m_points.push_back(mid); + m_points.push_back(point); + + TRect bbox; + int m = (int)m_points.size(); + std::vector points; + if (m == 3) { + // ho appena cominciato. devo disegnare un segmento + TThickPoint pa = m_points.front(); + points.push_back(pa); + points.push_back(mid); + bbox = m_bluredBrush->getBoundFromPoints(points); + updateWorkAndBackupRasters(bbox + m_lastRect); + m_tileSaver->save(bbox); + m_bluredBrush->addArc(pa, (mid + pa) * 0.5, mid, 1, 1); + m_lastRect += bbox; + } else { + points.push_back(m_points[m - 4]); + points.push_back(old); + points.push_back(mid); + bbox = m_bluredBrush->getBoundFromPoints(points); + updateWorkAndBackupRasters(bbox + m_lastRect); + m_tileSaver->save(bbox); + m_bluredBrush->addArc(m_points[m - 4], old, mid, 1, 1); + m_lastRect += bbox; + } + invalidateRect += ToolUtils::getBounds(points, maxThickness) - rasCenter; + + m_bluredBrush->updateDrawing(ti->getRaster(), m_backupRas, bbox, + m_styleId, m_drawOrder.getIndex()); + m_strokeRect += bbox; + } + } + + // clear & draw brush tip when drawing smooth stroke + if (m_smooth.getValue() != 0) { + TPointD halfThick(m_maxThick * 0.5, m_maxThick * 0.5); + invalidateRect += TRectD(m_brushPos - halfThick, m_brushPos + halfThick); + invalidateRect += TRectD(pos - halfThick, pos + halfThick); + } + + m_brushPos = m_mousePos = pos; + + invalidate(invalidateRect.enlarge(2)); +} + +//--------------------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::leftButtonUp(const TPointD &pos, + const TMouseEvent &e) { + bool isValid = m_enabled && m_active; + m_enabled = false; + if (!isValid) { + return; + } + double pressure = m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5; + finishRasterBrush(pos, pressure); +} + +//--------------------------------------------------------------------------------------------------------------- +/*! + * ドラッグ中にツールが切り替わった場合に備え、onDeactivate時とMouseRelease時にと同じ終了処理を行う +*/ +void ToonzRasterBrushTool::finishRasterBrush(const TPointD &pos, + double pressureVal) { + TToonzImageP ti = TImageP(getImage(true)); + + TPointD rasCenter = ti->getRaster()->getCenterD(); + TTool::Application *app = TTool::getApplication(); + TXshLevel *level = app->getCurrentLevel()->getLevel(); + TXshSimpleLevelP simLevel = level->getSimpleLevel(); + + /*-- + * 描画中にカレントフレームが変わっても、描画開始時のFidに対してUndoを記録する + * --*/ + TFrameId frameId = + m_workingFrameId.isEmptyFrame() ? getCurrentFid() : m_workingFrameId; + if (m_isMyPaintStyleSelected) { + TRasterCM32P ras = ti->getRaster(); + TPointD point(pos + rasCenter); + double pressure = m_pressure.getValue() ? pressureVal : 0.5; + + m_strokeSegmentRect.empty(); + m_toonz_brush->strokeTo(point, pressure, restartBrushTimer()); + m_toonz_brush->endStroke(); + TRect updateRect = m_strokeSegmentRect * ras->getBounds(); + if (!updateRect.isEmpty()) { + // ras->extract(updateRect)->copy(m_workRaster->extract(updateRect)); + m_toonz_brush->updateDrawing(ras, m_backupRas, m_strokeSegmentRect, + m_styleId); + } + TPointD thickOffset(m_maxCursorThick * 0.5, + m_maxCursorThick * 0.5); // TODO + TRectD invalidateRect = convert(m_strokeSegmentRect) - rasCenter; + invalidateRect += TRectD(pos - thickOffset, pos + thickOffset); + invalidate(invalidateRect.enlarge(2.0)); + + if (m_toonz_brush) { + delete m_toonz_brush; + m_toonz_brush = 0; + } + + m_lastRect.empty(); + m_workRas->unlock(); + + if (m_tileSet->getTileCount() > 0) { + TRasterCM32P subras = ras->extract(m_strokeRect)->clone(); + TUndoManager::manager()->add(new MyPaintBrushUndo( + m_tileSet, simLevel.getPointer(), frameId, m_isFrameCreated, + m_isLevelCreated, subras, m_strokeRect.getP00())); + } + + } else if (m_rasterTrack && + (m_hardness.getValue() == 100 || m_pencil.getValue())) { + double thickness = m_pressure.getValue() + ? computeThickness(pressureVal, m_rasThickness) + : m_rasThickness.getValue().second; + + /*--- ストロークの最初にMaxサイズの円が描かれてしまう不具合を防止する ---*/ + if (m_pressure.getValue() && pressureVal == 1.0) + thickness = m_rasThickness.getValue().first; + + /*-- Pencilモードでなく、Hardness=100 の場合のブラシサイズを1段階下げる --*/ + if (!m_pencil.getValue()) thickness -= 1.0; + + TRectD invalidateRect; + TThickPoint thickPoint(pos + rasCenter, thickness); + std::vector pts; + if (m_smooth.getValue() == 0) { + pts.push_back(thickPoint); + } else { + m_smoothStroke.addPoint(thickPoint); + m_smoothStroke.endStroke(); + m_smoothStroke.getSmoothPoints(pts); + } + for (size_t i = 0; i < pts.size(); ++i) { + const TThickPoint &thickPoint = pts[i]; + m_rasterTrack->add(thickPoint); + m_tileSaver->save(m_rasterTrack->getLastRect()); + m_rasterTrack->generateLastPieceOfStroke(m_pencil.getValue(), true); + + std::vector brushPoints = m_rasterTrack->getPointsSequence(); + int m = (int)brushPoints.size(); + std::vector points; + if (m == 3) { + points.push_back(brushPoints[0]); + points.push_back(brushPoints[1]); + } else { + points.push_back(brushPoints[m - 4]); + points.push_back(brushPoints[m - 3]); + points.push_back(brushPoints[m - 2]); + } + int maxThickness = m_rasThickness.getValue().second; + invalidateRect += ToolUtils::getBounds(points, maxThickness) - rasCenter; + } + invalidate(invalidateRect.enlarge(2)); + + if (m_tileSet->getTileCount() > 0) { + TUndoManager::manager()->add(new RasterBrushUndo( + m_tileSet, m_rasterTrack->getPointsSequence(), + m_rasterTrack->getStyleId(), m_rasterTrack->isSelective(), + simLevel.getPointer(), frameId, m_pencil.getValue(), m_isFrameCreated, + m_isLevelCreated, m_rasterTrack->isPaletteOrder())); + } + delete m_rasterTrack; + m_rasterTrack = 0; + } else { + double maxThickness = m_rasThickness.getValue().second; + double thickness = (m_pressure.getValue()) + ? computeThickness(pressureVal, m_rasThickness) + : maxThickness; + TPointD rasCenter = ti->getRaster()->getCenterD(); + TRectD invalidateRect; + TThickPoint thickPoint(pos + rasCenter, thickness); + std::vector pts; + if (m_smooth.getValue() == 0) { + pts.push_back(thickPoint); + } else { + m_smoothStroke.addPoint(thickPoint); + m_smoothStroke.endStroke(); + m_smoothStroke.getSmoothPoints(pts); + } + // we need to skip the for-loop here if pts.size() == 0 or else + // (pts.size() - 1) becomes ULLONG_MAX since size_t is unsigned + if (pts.size() > 0) { + for (size_t i = 0; i < pts.size() - 1; ++i) { + TThickPoint old = m_points.back(); + + const TThickPoint &point = pts[i]; + TThickPoint mid((old + point) * 0.5, (point.thick + old.thick) * 0.5); + m_points.push_back(mid); + m_points.push_back(point); + + TRect bbox; + int m = (int)m_points.size(); + std::vector points; + if (m == 3) { + // ho appena cominciato. devo disegnare un segmento + TThickPoint pa = m_points.front(); + points.push_back(pa); + points.push_back(mid); + bbox = m_bluredBrush->getBoundFromPoints(points); + updateWorkAndBackupRasters(bbox + m_lastRect); + m_tileSaver->save(bbox); + m_bluredBrush->addArc(pa, (mid + pa) * 0.5, mid, 1, 1); + m_lastRect += bbox; + } else { + points.push_back(m_points[m - 4]); + points.push_back(old); + points.push_back(mid); + bbox = m_bluredBrush->getBoundFromPoints(points); + updateWorkAndBackupRasters(bbox + m_lastRect); + m_tileSaver->save(bbox); + m_bluredBrush->addArc(m_points[m - 4], old, mid, 1, 1); + m_lastRect += bbox; + } + + invalidateRect += + ToolUtils::getBounds(points, maxThickness) - rasCenter; + + m_bluredBrush->updateDrawing(ti->getRaster(), m_backupRas, bbox, + m_styleId, m_drawOrder.getIndex()); + m_strokeRect += bbox; + } + TThickPoint point = pts.back(); + m_points.push_back(point); + int m = m_points.size(); + std::vector points; + points.push_back(m_points[m - 3]); + points.push_back(m_points[m - 2]); + points.push_back(m_points[m - 1]); + TRect bbox = m_bluredBrush->getBoundFromPoints(points); + updateWorkAndBackupRasters(bbox); + m_tileSaver->save(bbox); + m_bluredBrush->addArc(points[0], points[1], points[2], 1, 1); + m_bluredBrush->updateDrawing(ti->getRaster(), m_backupRas, bbox, + m_styleId, m_drawOrder.getIndex()); + + invalidateRect += ToolUtils::getBounds(points, maxThickness) - rasCenter; + + m_lastRect += bbox; + m_strokeRect += bbox; + } + if (!invalidateRect.isEmpty()) invalidate(invalidateRect.enlarge(2)); + m_lastRect.empty(); + + delete m_bluredBrush; + m_bluredBrush = 0; + + if (m_tileSet->getTileCount() > 0) { + TUndoManager::manager()->add(new RasterBluredBrushUndo( + m_tileSet, m_points, m_styleId, (DrawOrder)m_drawOrder.getIndex(), + simLevel.getPointer(), frameId, m_rasThickness.getValue().second, + m_hardness.getValue() * 0.01, m_isFrameCreated, m_isLevelCreated)); + } + } + delete m_tileSaver; + + m_tileSaver = 0; + + /*-- FIdを指定して、描画中にフレームが動いても、 +   描画開始時のFidのサムネイルが更新されるようにする。--*/ + notifyImageChanged(frameId); + + m_strokeRect.empty(); + + ToolUtils::updateSaveBox(); + + /*-- 作業中のフレームをリセット --*/ + m_workingFrameId = TFrameId(); +} +//--------------------------------------------------------------------------------------------------------------- +// 明日はここをMyPaintのときにカーソルを消せるように修正する!!!!!! +void ToonzRasterBrushTool::mouseMove(const TPointD &pos, const TMouseEvent &e) { + qApp->processEvents(QEventLoop::ExcludeUserInputEvents); + + struct Locals { + ToonzRasterBrushTool *m_this; + + void setValue(TDoublePairProperty &prop, + const TDoublePairProperty::Value &value) { + prop.setValue(value); + + m_this->onPropertyChanged(prop.getName()); + TTool::getApplication()->getCurrentTool()->notifyToolChanged(); + } + + void addMinMax(TDoublePairProperty &prop, double add) { + if (add == 0.0) return; + const TDoublePairProperty::Range &range = prop.getRange(); + + TDoublePairProperty::Value value = prop.getValue(); + value.first = tcrop(value.first + add, range.first, range.second); + value.second = tcrop(value.second + add, range.first, range.second); + + setValue(prop, value); + } + + void addMinMaxSeparate(TDoublePairProperty &prop, double min, double max) { + if (min == 0.0 && max == 0.0) return; + const TDoublePairProperty::Range &range = prop.getRange(); + + TDoublePairProperty::Value value = prop.getValue(); + value.first += min; + value.second += max; + if (value.first > value.second) value.first = value.second; + value.first = tcrop(value.first, range.first, range.second); + value.second = tcrop(value.second, range.first, range.second); + + setValue(prop, value); + } + + } locals = {this}; + + // if (e.isAltPressed() && !e.isCtrlPressed()) { + // const TPointD &diff = pos - m_mousePos; + // double add = (fabs(diff.x) > fabs(diff.y)) ? diff.x : diff.y; + + // locals.addMinMax( + // TToonzImageP(getImage(false, 1)) ? m_rasThickness : m_thickness, add); + //} else + + double thickness = + (m_isMyPaintStyleSelected) ? (double)(m_maxCursorThick + 1) : m_maxThick; + TPointD halfThick(thickness * 0.5, thickness * 0.5); + TRectD invalidateRect(m_brushPos - halfThick, m_brushPos + halfThick); + + if (e.isCtrlPressed() && e.isAltPressed() && !e.isShiftPressed()) { + const TPointD &diff = pos - m_mousePos; + double max = diff.x / 2; + double min = diff.y / 2; + + locals.addMinMaxSeparate(m_rasThickness, min, max); + + double radius = m_rasThickness.getValue().second * 0.5; + invalidateRect += TRectD(m_brushPos - TPointD(radius, radius), + m_brushPos + TPointD(radius, radius)); + + } else { + m_mousePos = pos; + m_brushPos = pos; + + invalidateRect += TRectD(pos - halfThick, pos + halfThick); + } + + invalidate(invalidateRect.enlarge(2)); + + if (m_minThick == 0 && m_maxThick == 0) { + m_minThick = m_rasThickness.getValue().first; + m_maxThick = m_rasThickness.getValue().second; + } +} + +//------------------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::draw() { + /*--ショートカットでのツール切り替え時に赤点が描かれるのを防止する--*/ + if (m_minThick == 0 && m_maxThick == 0 && + !Preferences::instance()->getShow0ThickLines()) + return; + + TImageP img = getImage(false, 1); + + if (getApplication()->getCurrentObject()->isSpline()) return; + + // If toggled off, don't draw brush outline + if (!Preferences::instance()->isCursorOutlineEnabled()) return; + + // Draw the brush outline - change color when the Ink / Paint check is + // activated + if ((ToonzCheck::instance()->getChecks() & ToonzCheck::eInk) || + (ToonzCheck::instance()->getChecks() & ToonzCheck::ePaint) || + (ToonzCheck::instance()->getChecks() & ToonzCheck::eInk1)) + glColor3d(0.5, 0.8, 0.8); + // normally draw in red + else + glColor3d(1.0, 0.0, 0.0); + + if (m_isMyPaintStyleSelected) { + tglDrawCircle(m_brushPos, (m_minCursorThick + 1) * 0.5); + tglDrawCircle(m_brushPos, (m_maxCursorThick + 1) * 0.5); + return; + } + + if (TToonzImageP ti = img) { + TRasterP ras = ti->getRaster(); + int lx = ras->getLx(); + int ly = ras->getLy(); + drawEmptyCircle(m_brushPos, tround(m_minThick), lx % 2 == 0, ly % 2 == 0, + m_pencil.getValue()); + drawEmptyCircle(m_brushPos, tround(m_maxThick), lx % 2 == 0, ly % 2 == 0, + m_pencil.getValue()); + } else { + drawEmptyCircle(m_brushPos, tround(m_minThick), true, true, + m_pencil.getValue()); + drawEmptyCircle(m_brushPos, tround(m_maxThick), true, true, + m_pencil.getValue()); + } +} + +//-------------------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::onEnter() { + TImageP img = getImage(false); + + m_minThick = m_rasThickness.getValue().first; + m_maxThick = m_rasThickness.getValue().second; + updateCurrentStyle(); + + Application *app = getApplication(); + + m_styleId = app->getCurrentLevelStyleIndex(); + TColorStyle *cs = app->getCurrentLevelStyle(); + if (cs) { + TRasterStyleFx *rfx = cs->getRasterStyleFx(); + m_active = cs->isStrokeStyle() || (rfx && rfx->isInkStyle()); + m_currentColor = cs->getAverageColor(); + m_currentColor.m = 255; + } else { + m_currentColor = TPixel32::Black; + } + m_active = img; +} + +//---------------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::onLeave() { + m_minThick = 0; + m_maxThick = 0; + m_minCursorThick = 0; + m_maxCursorThick = 0; +} + +//---------------------------------------------------------------------------------------------------------- + +TPropertyGroup *ToonzRasterBrushTool::getProperties(int idx) { + if (!m_presetsLoaded) initPresets(); + + return &m_prop[idx]; +} + +//---------------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::onImageChanged() { + if (!isEnabled()) return; + + setWorkAndBackupImages(); +} + +//---------------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::setWorkAndBackupImages() { + TToonzImageP ti = (TToonzImageP)getImage(false, 1); + if (!ti) return; + TRasterP ras = ti->getRaster(); + TDimension dim = ras->getSize(); + + double hardness = m_hardness.getValue() * 0.01; + if (!m_isMyPaintStyleSelected && hardness == 1.0 && + ras->getPixelSize() == 4) { + m_workRas = TRaster32P(); + m_backupRas = TRasterCM32P(); + } else { + if (!m_workRas || m_workRas->getLx() > dim.lx || + m_workRas->getLy() > dim.ly) + m_workRas = TRaster32P(dim); + if (!m_backupRas || m_backupRas->getLx() > dim.lx || + m_backupRas->getLy() > dim.ly) + m_backupRas = TRasterCM32P(dim); + + m_strokeRect.empty(); + m_lastRect.empty(); + } +} + +//------------------------------------------------------------------ + +bool ToonzRasterBrushTool::onPropertyChanged(std::string propertyName) { + // Set the following to true whenever a different piece of interface must + // be refreshed - done once at the end. + bool notifyTool = false; + + /*--- 変更されたPropertyに合わせて処理を分ける ---*/ + + /*--- determine which type of brush to be modified ---*/ + if (propertyName == m_rasThickness.getName()) { + RasterBrushMinSize = m_rasThickness.getValue().first; + RasterBrushMaxSize = m_rasThickness.getValue().second; + + m_minThick = m_rasThickness.getValue().first; + m_maxThick = m_rasThickness.getValue().second; + } else if (propertyName == m_smooth.getName()) { + BrushSmooth = m_smooth.getValue(); + } else if (propertyName == m_preset.getName()) { + loadPreset(); + notifyTool = true; + } else if (propertyName == m_drawOrder.getName()) { + BrushDrawOrder = m_drawOrder.getIndex(); + } else if (propertyName == m_pencil.getName()) { + RasterBrushPencilMode = m_pencil.getValue(); + } else if (propertyName == m_pressure.getName()) { + BrushPressureSensitivity = m_pressure.getValue(); + } else if (propertyName == m_hardness.getName()) + setWorkAndBackupImages(); + else if (propertyName == m_modifierSize.getName()) + RasterBrushModifierSize = m_modifierSize.getValue(); + + if (propertyName == m_hardness.getName() || + propertyName == m_rasThickness.getName()) { + m_brushPad = getBrushPad(m_rasThickness.getValue().second, + m_hardness.getValue() * 0.01); + TRectD rect(m_mousePos - TPointD(m_maxThick + 2, m_maxThick + 2), + m_mousePos + TPointD(m_maxThick + 2, m_maxThick + 2)); + invalidate(rect); + } + + if (propertyName != m_preset.getName() && + m_preset.getValue() != CUSTOM_WSTR) { + m_preset.setValue(CUSTOM_WSTR); + notifyTool = true; + } + + if (notifyTool) getApplication()->getCurrentTool()->notifyToolChanged(); + + return true; +} + +//------------------------------------------------------------------ + +void ToonzRasterBrushTool::initPresets() { + if (!m_presetsLoaded) { + // If necessary, load the presets from file + m_presetsLoaded = true; + m_presetsManager.load(TEnv::getConfigDir() + "brush_toonzraster.txt"); + } + + // Rebuild the presets property entries + const std::set &presets = m_presetsManager.presets(); + + m_preset.deleteAllValues(); + m_preset.addValue(CUSTOM_WSTR); + m_preset.setItemUIName(CUSTOM_WSTR, tr("")); + + std::set::const_iterator it, end = presets.end(); + for (it = presets.begin(); it != end; ++it) m_preset.addValue(it->m_name); +} + +//---------------------------------------------------------------------------------------------------------- + +void ToonzRasterBrushTool::loadPreset() { + const std::set &presets = m_presetsManager.presets(); + std::set::const_iterator it; + + it = presets.find(BrushData(m_preset.getValue())); + if (it == presets.end()) return; + + const BrushData &preset = *it; + + try // Don't bother with RangeErrors + { + m_rasThickness.setValue( + TDoublePairProperty::Value(std::max(preset.m_min, 1.0), preset.m_max)); + m_brushPad = ToolUtils::getBrushPad(preset.m_max, preset.m_hardness * 0.01); + m_smooth.setValue(preset.m_smooth, true); + m_hardness.setValue(preset.m_hardness, true); + m_drawOrder.setIndex(preset.m_drawOrder); + m_pencil.setValue(preset.m_pencil); + m_pressure.setValue(preset.m_pressure); + m_modifierSize.setValue(preset.m_modifierSize); + + } catch (...) { + } +} + +//------------------------------------------------------------------ + +void ToonzRasterBrushTool::addPreset(QString name) { + // Build the preset + BrushData preset(name.toStdWString()); + + preset.m_min = m_rasThickness.getValue().first; + preset.m_max = m_rasThickness.getValue().second; + + preset.m_smooth = m_smooth.getValue(); + preset.m_hardness = m_hardness.getValue(); + preset.m_drawOrder = m_drawOrder.getIndex(); + preset.m_pencil = m_pencil.getValue(); + preset.m_pressure = m_pressure.getValue(); + preset.m_modifierSize = m_modifierSize.getValue(); + + // Pass the preset to the manager + m_presetsManager.addPreset(preset); + + // Reinitialize the associated preset enum + initPresets(); + + // Set the value to the specified one + m_preset.setValue(preset.m_name); +} + +//------------------------------------------------------------------ + +void ToonzRasterBrushTool::removePreset() { + std::wstring name(m_preset.getValue()); + if (name == CUSTOM_WSTR) return; + + m_presetsManager.removePreset(name); + initPresets(); + + // No parameter change, and set the preset value to custom + m_preset.setValue(CUSTOM_WSTR); +} + +//------------------------------------------------------------------ +/*! Brush、PaintBrush、EraserToolがPencilModeのときにTrueを返す +*/ +bool ToonzRasterBrushTool::isPencilModeActive() { + return getTargetType() == TTool::ToonzImage && m_pencil.getValue(); +} + +//------------------------------------------------------------------ + +void ToonzRasterBrushTool::onColorStyleChanged() { + // in case the style switched while drawing + if (m_tileSaver) { + bool isValid = m_enabled && m_active; + m_enabled = false; + if (isValid) { + finishRasterBrush(m_mousePos, 1); + } + } + + TTool::Application *app = getApplication(); + TMyPaintBrushStyle *mpbs = + dynamic_cast(app->getCurrentLevelStyle()); + m_isMyPaintStyleSelected = (mpbs) ? true : false; + setWorkAndBackupImages(); + getApplication()->getCurrentTool()->notifyToolChanged(); +} + +//------------------------------------------------------------------ + +double ToonzRasterBrushTool::restartBrushTimer() { + double dtime = m_brushTimer.nsecsElapsed() * 1e-9; + m_brushTimer.restart(); + return dtime; +} + +//------------------------------------------------------------------ + +void ToonzRasterBrushTool::updateCurrentStyle() { + if (m_isMyPaintStyleSelected) { + TTool::Application *app = TTool::getApplication(); + TMyPaintBrushStyle *brushStyle = + dynamic_cast(app->getCurrentLevelStyle()); + double radiusLog = brushStyle->getBrush().getBaseValue( + MYPAINT_BRUSH_SETTING_RADIUS_LOGARITHMIC) + + m_modifierSize.getValue() * log(2.0); + double radius = exp(radiusLog); + m_minCursorThick = m_maxCursorThick = (int)std::round(2.0 * radius); + } +} +//========================================================================================================== + +ToonzRasterBrushToolNotifier::ToonzRasterBrushToolNotifier( + ToonzRasterBrushTool *tool) + : m_tool(tool) { + if (TTool::Application *app = m_tool->getApplication()) { + if (TPaletteHandle *paletteHandle = app->getCurrentPalette()) { + bool ret; + ret = connect(paletteHandle, SIGNAL(colorStyleChanged(bool)), this, + SLOT(onColorStyleChanged())); + ret = ret && connect(paletteHandle, SIGNAL(colorStyleSwitched()), this, + SLOT(onColorStyleChanged())); + ret = ret && connect(paletteHandle, SIGNAL(paletteSwitched()), this, + SLOT(onColorStyleChanged())); + assert(ret); + } + } + onColorStyleChanged(); +} + +//========================================================================================================== + +// Tools instantiation + +ToonzRasterBrushTool toonzPencil("T_Brush", + TTool::ToonzImage | TTool::EmptyTarget); + +//******************************************************************************* +// Brush Data implementation +//******************************************************************************* + +BrushData::BrushData() + : m_name() + , m_min(0.0) + , m_max(0.0) + , m_smooth(0.0) + , m_hardness(0.0) + , m_opacityMin(0.0) + , m_opacityMax(0.0) + , m_drawOrder(0) + , m_pencil(false) + , m_pressure(false) + , m_modifierSize(0.0) + , m_modifierOpacity(0.0) + , m_modifierEraser(0.0) + , m_modifierLockAlpha(0.0) {} + +//---------------------------------------------------------------------------------------------------------- + +BrushData::BrushData(const std::wstring &name) + : m_name(name) + , m_min(0.0) + , m_max(0.0) + , m_smooth(0.0) + , m_hardness(0.0) + , m_opacityMin(0.0) + , m_opacityMax(0.0) + , m_drawOrder(0) + , m_pencil(false) + , m_pressure(false) + , m_modifierSize(0.0) + , m_modifierOpacity(0.0) + , m_modifierEraser(0.0) + , m_modifierLockAlpha(0.0) {} + +//---------------------------------------------------------------------------------------------------------- + +void BrushData::saveData(TOStream &os) { + os.openChild("Name"); + os << m_name; + os.closeChild(); + os.openChild("Thickness"); + os << m_min << m_max; + os.closeChild(); + os.openChild("Smooth"); + os << m_smooth; + os.closeChild(); + os.openChild("Hardness"); + os << m_hardness; + os.closeChild(); + os.openChild("Opacity"); + os << m_opacityMin << m_opacityMax; + os.closeChild(); + os.openChild("Draw_Order"); + os << m_drawOrder; + os.closeChild(); + os.openChild("Pencil"); + os << (int)m_pencil; + os.closeChild(); + os.openChild("Pressure_Sensitivity"); + os << (int)m_pressure; + os.closeChild(); + os.openChild("Modifier_Size"); + os << m_modifierSize; + os.closeChild(); + os.openChild("Modifier_Opacity"); + os << m_modifierOpacity; + os.closeChild(); + os.openChild("Modifier_Eraser"); + os << (int)m_modifierEraser; + os.closeChild(); + os.openChild("Modifier_LockAlpha"); + os << (int)m_modifierLockAlpha; + os.closeChild(); +} + +//---------------------------------------------------------------------------------------------------------- + +void BrushData::loadData(TIStream &is) { + std::string tagName; + int val; + + while (is.matchTag(tagName)) { + if (tagName == "Name") + is >> m_name, is.matchEndTag(); + else if (tagName == "Thickness") + is >> m_min >> m_max, is.matchEndTag(); + else if (tagName == "Smooth") + is >> m_smooth, is.matchEndTag(); + else if (tagName == "Hardness") + is >> m_hardness, is.matchEndTag(); + else if (tagName == "Opacity") + is >> m_opacityMin >> m_opacityMax, is.matchEndTag(); + else if (tagName == "Selective" || + tagName == "Draw_Order") // "Selective" is left to keep backward + // compatibility + is >> m_drawOrder, is.matchEndTag(); + else if (tagName == "Pencil") + is >> val, m_pencil = val, is.matchEndTag(); + else if (tagName == "Pressure_Sensitivity") + is >> val, m_pressure = val, is.matchEndTag(); + else if (tagName == "Modifier_Size") + is >> m_modifierSize, is.matchEndTag(); + else if (tagName == "Modifier_Opacity") + is >> m_modifierOpacity, is.matchEndTag(); + else if (tagName == "Modifier_Eraser") + is >> val, m_modifierEraser = val, is.matchEndTag(); + else if (tagName == "Modifier_LockAlpha") + is >> val, m_modifierLockAlpha = val, is.matchEndTag(); + else + is.skipCurrentTag(); + } +} + +//---------------------------------------------------------------------------------------------------------- + +PERSIST_IDENTIFIER(BrushData, "BrushData"); + +//******************************************************************************* +// Brush Preset Manager implementation +//******************************************************************************* + +void BrushPresetManager::load(const TFilePath &fp) { + m_fp = fp; + + std::string tagName; + BrushData data; + + TIStream is(m_fp); + try { + while (is.matchTag(tagName)) { + if (tagName == "version") { + VersionNumber version; + is >> version.first >> version.second; + + is.setVersion(version); + is.matchEndTag(); + } else if (tagName == "brushes") { + while (is.matchTag(tagName)) { + if (tagName == "brush") { + is >> data, m_presets.insert(data); + is.matchEndTag(); + } else + is.skipCurrentTag(); + } + + is.matchEndTag(); + } else + is.skipCurrentTag(); + } + } catch (...) { + } +} + +//------------------------------------------------------------------ + +void BrushPresetManager::save() { + TOStream os(m_fp); + + os.openChild("version"); + os << 1 << 19; + os.closeChild(); + + os.openChild("brushes"); + + std::set::iterator it, end = m_presets.end(); + for (it = m_presets.begin(); it != end; ++it) { + os.openChild("brush"); + os << (TPersist &)*it; + os.closeChild(); + } + + os.closeChild(); +} + +//------------------------------------------------------------------ + +void BrushPresetManager::addPreset(const BrushData &data) { + m_presets.erase(data); // Overwriting insertion + m_presets.insert(data); + save(); +} + +//------------------------------------------------------------------ + +void BrushPresetManager::removePreset(const std::wstring &name) { + m_presets.erase(BrushData(name)); + save(); +} diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.h b/toonz/sources/tnztools/toonzrasterbrushtool.h new file mode 100644 index 0000000..16d1a34 --- /dev/null +++ b/toonz/sources/tnztools/toonzrasterbrushtool.h @@ -0,0 +1,246 @@ +#pragma once + +#ifndef TOONZRASTERBRUSHTOOL_H +#define TOONZRASTERBRUSHTOOL_H + +#include "tgeometry.h" +#include "tproperty.h" +#include "trasterimage.h" +#include "ttoonzimage.h" +#include "tstroke.h" +#include "toonz/strokegenerator.h" + +#include "tools/tool.h" +#include "tools/cursors.h" +#include "mypainttoonzbrush.h" + +#include +#include +#include + +//-------------------------------------------------------------- + +// Forward declarations + +class TTileSetCM32; +class TTileSaverCM32; +class RasterStrokeGenerator; +class BluredBrush; +class ToonzRasterBrushToolNotifier; + +//-------------------------------------------------------------- + +//************************************************************************ +// Toonz Raster Brush Data declaration +//************************************************************************ + +struct BrushData final : public TPersist { + PERSIST_DECLARATION(BrushData) + // frameRange, snapSensitivity and snap are not included + // Those options are not really a part of the brush settings, + // just the overall tool. + + std::wstring m_name; + double m_min, m_max, m_smooth, m_hardness, m_opacityMin, m_opacityMax; + bool m_pencil, m_pressure; + int m_drawOrder; + double m_modifierSize, m_modifierOpacity; + bool m_modifierEraser, m_modifierLockAlpha; + + BrushData(); + BrushData(const std::wstring &name); + + bool operator<(const BrushData &other) const { return m_name < other.m_name; } + + void saveData(TOStream &os) override; + void loadData(TIStream &is) override; +}; + +//************************************************************************ +// Toonz Raster Brush Preset Manager declaration +//************************************************************************ + +class BrushPresetManager { + TFilePath m_fp; //!< Presets file path + std::set m_presets; //!< Current presets container + +public: + BrushPresetManager() {} + + void load(const TFilePath &fp); + void save(); + + const TFilePath &path() { return m_fp; }; + const std::set &presets() const { return m_presets; } + + void addPreset(const BrushData &data); + void removePreset(const std::wstring &name); +}; + +//************************************************************************ +// Smooth Stroke declaration +// Brush stroke smoothing buffer. +//************************************************************************ +class SmoothStroke { +public: + SmoothStroke() {} + ~SmoothStroke() {} + + // begin stroke + // smooth is smooth strength, from 0 to 100 + void beginStroke(int smooth); + // add stroke point + void addPoint(const TThickPoint &point); + // end stroke + void endStroke(); + // Get generated stroke points which has been smoothed. + // Both addPoint() and endStroke() generate new smoothed points. + // This method will removed generated points + void getSmoothPoints(std::vector &smoothPoints); + // Remove all points - used for straight lines + void clearPoints(); + +private: + void generatePoints(); + +private: + int m_smooth; + int m_outputIndex; + int m_readIndex; + std::vector m_rawPoints; + std::vector m_outputPoints; +}; +//************************************************************************ +// Toonz Raster Brush Tool declaration +//************************************************************************ + +class ToonzRasterBrushTool final : public TTool, public RasterController { + Q_DECLARE_TR_FUNCTIONS(ToonzRasterBrushTool) + + void updateCurrentStyle(); + double restartBrushTimer(); + +public: + ToonzRasterBrushTool(std::string name, int targetType); + + ToolType getToolType() const override { return TTool::LevelWriteTool; } + + ToolOptionsBox *createOptionsBox() override; + + void updateTranslation() override; + + void onActivate() override; + void onDeactivate() override; + + bool preLeftButtonDown() override; + void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override; + void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override; + void leftButtonUp(const TPointD &pos, const TMouseEvent &e) override; + void mouseMove(const TPointD &pos, const TMouseEvent &e) override; + + void draw() override; + + void onEnter() override; + void onLeave() override; + + int getCursorId() const override { return ToolCursor::PenCursor; } + + TPropertyGroup *getProperties(int targetType) override; + bool onPropertyChanged(std::string propertyName) override; + void onImageChanged() override; + void setWorkAndBackupImages(); + void updateWorkAndBackupRasters(const TRect &rect); + + void initPresets(); + void loadPreset(); + void addPreset(QString name); + void removePreset(); + + void finishRasterBrush(const TPointD &pos, double pressureVal); + // return true if the pencil mode is active in the Brush / PaintBrush / Eraser + // Tools. + bool isPencilModeActive() override; + + void onColorStyleChanged(); + bool askRead(const TRect &rect) override; + bool askWrite(const TRect &rect) override; + bool isMyPaintStyleSelected() { return m_isMyPaintStyleSelected; } + +protected: + TPropertyGroup m_prop[2]; + + TDoublePairProperty m_rasThickness; + TDoubleProperty m_smooth; + TDoubleProperty m_hardness; + TEnumProperty m_preset; + TEnumProperty m_drawOrder; + TBoolProperty m_pencil; + TBoolProperty m_pressure; + TDoubleProperty m_modifierSize; + + RasterStrokeGenerator *m_rasterTrack; + TTileSetCM32 *m_tileSet; + TTileSaverCM32 *m_tileSaver; + TPixel32 m_currentColor; + int m_styleId; + double m_minThick, m_maxThick; + + int m_targetType; + TPointD m_dpiScale, + m_mousePos, //!< Current mouse position, in world coordinates. + m_brushPos; //!< World position the brush will be painted at. + + BluredBrush *m_bluredBrush; + QRadialGradient m_brushPad; + + TRasterCM32P m_backupRas; + TRaster32P m_workRas; + + std::vector m_points; + TRect m_strokeRect, m_lastRect, + m_strokeSegmentRect; // used with mypaint brush + + SmoothStroke m_smoothStroke; + + BrushPresetManager + m_presetsManager; //!< Manager for presets of this tool instance + + bool m_active, m_enabled, + m_isPrompting, //!< Whether the tool is prompting for spline + //! substitution. + m_firstTime, m_presetsLoaded; + + /*--- +作業中のFrameIdをクリック時に保存し、マウスリリース時(Undoの登録時)に別のフレームに +移動していたときの不具合を修正する。---*/ + TFrameId m_workingFrameId; + + ToonzRasterBrushToolNotifier *m_notifier; + bool m_isMyPaintStyleSelected = false; + MyPaintToonzBrush *m_toonz_brush = 0; + QElapsedTimer m_brushTimer; + int m_minCursorThick, m_maxCursorThick; + +protected: + static void drawLine(const TPointD &point, const TPointD ¢re, + bool horizontal, bool isDecimal); + static void drawEmptyCircle(TPointD point, int thick, bool isLxEven, + bool isLyEven, bool isPencil); +}; + +//------------------------------------------------------------ + +class ToonzRasterBrushToolNotifier final : public QObject { + Q_OBJECT + + ToonzRasterBrushTool *m_tool; + +public: + ToonzRasterBrushToolNotifier(ToonzRasterBrushTool *tool); + +protected slots: + // void onCanvasSizeChanged() { m_tool->onCanvasSizeChanged(); } + void onColorStyleChanged() { m_tool->onColorStyleChanged(); } +}; + +#endif // TOONZRASTERBRUSHTOOL_H diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.cpp b/toonz/sources/tnztools/toonzvectorbrushtool.cpp new file mode 100644 index 0000000..c539159 --- /dev/null +++ b/toonz/sources/tnztools/toonzvectorbrushtool.cpp @@ -0,0 +1,1776 @@ + + +#include "toonzvectorbrushtool.h" + +// TnzTools includes +#include "tools/toolhandle.h" +#include "tools/toolutils.h" +#include "tools/tooloptions.h" +#include "bluredbrush.h" + +// TnzQt includes +#include "toonzqt/dvdialog.h" +#include "toonzqt/imageutils.h" + +// TnzLib includes +#include "toonz/tobjecthandle.h" +#include "toonz/txsheethandle.h" +#include "toonz/txshlevelhandle.h" +#include "toonz/tframehandle.h" +#include "toonz/tcolumnhandle.h" +#include "toonz/txsheet.h" +#include "toonz/tstageobject.h" +#include "toonz/tstageobjectspline.h" +#include "toonz/rasterstrokegenerator.h" +#include "toonz/ttileset.h" +#include "toonz/txshsimplelevel.h" +#include "toonz/toonzimageutils.h" +#include "toonz/palettecontroller.h" +#include "toonz/stage2.h" +#include "toonz/preferences.h" + +// TnzCore includes +#include "tstream.h" +#include "tcolorstyles.h" +#include "tvectorimage.h" +#include "tenv.h" +#include "tregion.h" +#include "tinbetween.h" + +#include "tgl.h" +#include "trop.h" + +// Qt includes +#include + +using namespace ToolUtils; + +TEnv::DoubleVar V_VectorBrushMinSize("InknpaintVectorBrushMinSize", 1); +TEnv::DoubleVar V_VectorBrushMaxSize("InknpaintVectorBrushMaxSize", 5); +TEnv::IntVar V_VectorCapStyle("InknpaintVectorCapStyle", 1); +TEnv::IntVar V_VectorJoinStyle("InknpaintVectorJoinStyle", 1); +TEnv::IntVar V_VectorMiterValue("InknpaintVectorMiterValue", 4); +TEnv::DoubleVar V_BrushAccuracy("InknpaintBrushAccuracy", 20); +TEnv::DoubleVar V_BrushSmooth("InknpaintBrushSmooth", 0); +TEnv::IntVar V_BrushBreakSharpAngles("InknpaintBrushBreakSharpAngles", 0); +TEnv::IntVar V_BrushPressureSensitivity("InknpaintBrushPressureSensitivity", 1); +TEnv::IntVar V_VectorBrushFrameRange("VectorBrushFrameRange", 0); +TEnv::IntVar V_VectorBrushSnap("VectorBrushSnap", 0); +TEnv::IntVar V_VectorBrushSnapSensitivity("VectorBrushSnapSensitivity", 0); + +//------------------------------------------------------------------- + +#define ROUNDC_WSTR L"round_cap" +#define BUTT_WSTR L"butt_cap" +#define PROJECTING_WSTR L"projecting_cap" +#define ROUNDJ_WSTR L"round_join" +#define BEVEL_WSTR L"bevel_join" +#define MITER_WSTR L"miter_join" +#define CUSTOM_WSTR L"" + +#define LINEAR_WSTR L"Linear" +#define EASEIN_WSTR L"In" +#define EASEOUT_WSTR L"Out" +#define EASEINOUT_WSTR L"In&Out" + +#define LOW_WSTR L"Low" +#define MEDIUM_WSTR L"Med" +#define HIGH_WSTR L"High" + +const double SNAPPING_LOW = 5.0; +const double SNAPPING_MEDIUM = 25.0; +const double SNAPPING_HIGH = 100.0; +//------------------------------------------------------------------- +// +// (Da mettere in libreria) : funzioni che spezzano una stroke +// nei suoi punti angolosi. Lo facciamo specialmente per limitare +// i problemi di fill. +// +//------------------------------------------------------------------- + +// +// Split a stroke in n+1 parts, according to n parameter values +// Input: +// stroke = stroke to split +// parameterValues[] = vector of parameters where I want to split the +// stroke +// assert: 0 ¶meterValues, + std::vector &strokes) { + TThickPoint p2; + std::vector points; + TThickPoint lastPoint = stroke->getControlPoint(0); + int n = parameterValues.size(); + int chunk; + double t; + int last_chunk = -1, startPoint = 0; + double lastLocT = 0; + + for (int i = 0; i < n; i++) { + points.push_back(lastPoint); // Add first point of the stroke + double w = + parameterValues[i]; // Global parameter. along the stroke 0<=w<=1 + stroke->getChunkAndT(w, chunk, + t); // t: local parameter in the chunk-th quadratic + + if (i == 0) + startPoint = 1; + else { + int indexAfterLastT = + stroke->getControlPointIndexAfterParameter(parameterValues[i - 1]); + startPoint = indexAfterLastT; + if ((indexAfterLastT & 1) && lastLocT != 1) startPoint++; + } + int endPoint = 2 * chunk + 1; + if (lastLocT != 1 && i > 0) { + if (last_chunk != chunk || t == 1) + points.push_back(p2); // If the last local t is not an extreme + // add the point p2 + } + + for (int j = startPoint; j < endPoint; j++) + points.push_back(stroke->getControlPoint(j)); + + TThickPoint p, A, B, C; + p = stroke->getPoint(w); + C = stroke->getControlPoint(2 * chunk + 2); + B = stroke->getControlPoint(2 * chunk + 1); + A = stroke->getControlPoint(2 * chunk); + p.thick = A.thick; + + if (last_chunk != chunk) { + TThickPoint p1 = (1 - t) * A + t * B; + points.push_back(p1); + p.thick = p1.thick; + } else { + if (t != 1) { + // If the i-th cut point belong to the same chunk of the (i-1)-th cut + // point. + double tInters = lastLocT / t; + TThickPoint p11 = (1 - t) * A + t * B; + TThickPoint p1 = (1 - tInters) * p11 + tInters * p; + points.push_back(p1); + p.thick = p1.thick; + } + } + + points.push_back(p); + + if (t != 1) p2 = (1 - t) * B + t * C; + + assert(points.size() & 1); + + // Add new stroke + TStroke *strokeAdd = new TStroke(points); + strokeAdd->setStyle(stroke->getStyle()); + strokeAdd->outlineOptions() = stroke->outlineOptions(); + strokes.push_back(strokeAdd); + + lastPoint = p; + last_chunk = chunk; + lastLocT = t; + points.clear(); + } + // Add end stroke + points.push_back(lastPoint); + + if (lastLocT != 1) points.push_back(p2); + + startPoint = + stroke->getControlPointIndexAfterParameter(parameterValues[n - 1]); + if ((stroke->getControlPointIndexAfterParameter(parameterValues[n - 1]) & + 1) && + lastLocT != 1) + startPoint++; + for (int j = startPoint; j < stroke->getControlPointCount(); j++) + points.push_back(stroke->getControlPoint(j)); + + assert(points.size() & 1); + TStroke *strokeAdd = new TStroke(points); + strokeAdd->setStyle(stroke->getStyle()); + strokeAdd->outlineOptions() = stroke->outlineOptions(); + strokes.push_back(strokeAdd); + points.clear(); +} + +// Compute Parametric Curve Curvature +// By Formula: +// k(t)=(|p'(t) x p''(t)|)/Norm2(p')^3 +// p(t) is parametric curve +// Input: +// dp = First Derivate. +// ddp = Second Derivate +// Output: +// return curvature value. +// Note: if the curve is a single point (that's dp=0) or it is a straight +// line (that's ddp=0) return 0 + +static double curvature(TPointD dp, TPointD ddp) { + if (dp == TPointD(0, 0)) + return 0; + else + return fabs(cross(dp, ddp) / pow(norm2(dp), 1.5)); +} + +// Find the max curvature points of a stroke. +// Input: +// stroke. +// angoloLim = Value (radians) of the Corner between two tangent vector. +// Up this value the two corner can be considered angular. +// curvMaxLim = Value of the max curvature. +// Up this value the point can be considered a max curvature +// point. +// Output: +// parameterValues = vector of max curvature parameter points + +static void findMaxCurvPoints(TStroke *stroke, const float &angoloLim, + const float &curvMaxLim, + std::vector ¶meterValues) { + TPointD tg1, tg2; // Tangent vectors + + TPointD dp, ddp; // First and Second derivate. + + parameterValues.clear(); + int cpn = stroke ? stroke->getControlPointCount() : 0; + for (int j = 2; j < cpn; j += 2) { + TPointD p0 = stroke->getControlPoint(j - 2); + TPointD p1 = stroke->getControlPoint(j - 1); + TPointD p2 = stroke->getControlPoint(j); + + TPointD q = p1 - (p0 + p2) * 0.5; + + // Search corner point + if (j > 2) { + tg2 = -p0 + p2 + 2 * q; // Tangent vector to this chunk at t=0 + double prod_scal = + tg2 * tg1; // Inner product between tangent vectors at t=0. + assert(tg1 != TPointD(0, 0) || tg2 != TPointD(0, 0)); + // Compute corner between two tangent vectors + double angolo = + acos(prod_scal / (pow(norm2(tg2), 0.5) * pow(norm2(tg1), 0.5))); + + // Add corner point + if (angolo > angoloLim) { + double w = getWfromChunkAndT(stroke, (UINT)(0.5 * (j - 2)), + 0); // transform lacal t to global t + parameterValues.push_back(w); + } + } + tg1 = -p0 + p2 - 2 * q; // Tangent vector to this chunk at t=1 + + // End search corner point + + // Search max curvature point + // Value of t where the curvature function has got an extreme. + // (Point where first derivate is null) + double estremo_int = 0; + double t = -1; + if (q != TPointD(0, 0)) { + t = 0.25 * (2 * q.x * q.x + 2 * q.y * q.y - q.x * p0.x + q.x * p2.x - + q.y * p0.y + q.y * p2.y) / + (q.x * q.x + q.y * q.y); + + dp = -p0 + p2 + 2 * q - 4 * t * q; // First derivate of the curve + ddp = -4 * q; // Second derivate of the curve + estremo_int = curvature(dp, ddp); + + double h = 0.01; + dp = -p0 + p2 + 2 * q - 4 * (t + h) * q; + double c_dx = curvature(dp, ddp); + dp = -p0 + p2 + 2 * q - 4 * (t - h) * q; + double c_sx = curvature(dp, ddp); + // Check the point is a max and not a minimum + if (estremo_int < c_dx && estremo_int < c_sx) { + estremo_int = 0; + } + } + double curv_max = estremo_int; + + // Compute curvature at the extreme of interval [0,1] + // Compute curvature at t=0 (Left extreme) + dp = -p0 + p2 + 2 * q; + double estremo_sx = curvature(dp, ddp); + + // Compute curvature at t=1 (Right extreme) + dp = -p0 + p2 - 2 * q; + double estremo_dx = curvature(dp, ddp); + + // Compare curvature at the extreme of interval [0,1] with the internal + // value + double t_ext; + if (estremo_sx >= estremo_dx) + t_ext = 0; + else + t_ext = 1; + double maxEstremi = std::max(estremo_dx, estremo_sx); + if (maxEstremi > estremo_int) { + t = t_ext; + curv_max = maxEstremi; + } + + // Add max curvature point + if (t >= 0 && t <= 1 && curv_max > curvMaxLim) { + double w = getWfromChunkAndT(stroke, (UINT)(0.5 * (j - 2)), + t); // transform local t to global t + parameterValues.push_back(w); + } + // End search max curvature point + } + // Delete duplicate of parameterValues + // Because some max cuvature point can coincide with the corner point + if ((int)parameterValues.size() > 1) { + std::sort(parameterValues.begin(), parameterValues.end()); + parameterValues.erase( + std::unique(parameterValues.begin(), parameterValues.end()), + parameterValues.end()); + } +} + +static void addStroke(TTool::Application *application, const TVectorImageP &vi, + TStroke *stroke, bool breakAngles, bool frameCreated, + bool levelCreated, TXshSimpleLevel *sLevel = NULL, + TFrameId fid = TFrameId::NO_FRAME) { + QMutexLocker lock(vi->getMutex()); + + if (application->getCurrentObject()->isSpline()) { + application->getCurrentXsheet()->notifyXsheetChanged(); + return; + } + + std::vector corners; + std::vector strokes; + + const float angoloLim = + 1; // Value (radians) of the Corner between two tangent vector. + // Up this value the two corner can be considered angular. + const float curvMaxLim = 0.8; // Value of the max curvature. + // Up this value the point can be considered a max curvature point. + + findMaxCurvPoints(stroke, angoloLim, curvMaxLim, corners); + TXshSimpleLevel *sl; + if (!sLevel) { + sl = application->getCurrentLevel()->getSimpleLevel(); + } else { + sl = sLevel; + } + TFrameId id = application->getCurrentTool()->getTool()->getCurrentFid(); + if (id == TFrameId::NO_FRAME && fid != TFrameId::NO_FRAME) id = fid; + if (!corners.empty()) { + if (breakAngles) + split(stroke, corners, strokes); + else + strokes.push_back(new TStroke(*stroke)); + + int n = strokes.size(); + + TUndoManager::manager()->beginBlock(); + for (int i = 0; i < n; i++) { + std::vector *fillInformation = + new std::vector; + ImageUtils::getFillingInformationOverlappingArea(vi, *fillInformation, + stroke->getBBox()); + TStroke *str = new TStroke(*strokes[i]); + vi->addStroke(str); + TUndoManager::manager()->add(new UndoPencil(str, fillInformation, sl, id, + frameCreated, levelCreated)); + } + TUndoManager::manager()->endBlock(); + } else { + std::vector *fillInformation = + new std::vector; + ImageUtils::getFillingInformationOverlappingArea(vi, *fillInformation, + stroke->getBBox()); + TStroke *str = new TStroke(*stroke); + vi->addStroke(str); + TUndoManager::manager()->add(new UndoPencil(str, fillInformation, sl, id, + frameCreated, levelCreated)); + } + + // Update regions. It will call roundStroke() in + // TVectorImage::Imp::findIntersections(). + // roundStroke() will slightly modify all the stroke positions. + // It is needed to update information for Fill Check. + vi->findRegions(); + + for (int k = 0; k < (int)strokes.size(); k++) delete strokes[k]; + strokes.clear(); + + application->getCurrentTool()->getTool()->notifyImageChanged(); +} + +//------------------------------------------------------------------- +// +// Gennaro: end +// +//------------------------------------------------------------------- + +//=================================================================== +// +// Helper functions and classes +// +//------------------------------------------------------------------- + +namespace { + +//------------------------------------------------------------------- + +void addStrokeToImage(TTool::Application *application, const TVectorImageP &vi, + TStroke *stroke, bool breakAngles, bool frameCreated, + bool levelCreated, TXshSimpleLevel *sLevel = NULL, + TFrameId id = TFrameId::NO_FRAME) { + QMutexLocker lock(vi->getMutex()); + addStroke(application, vi.getPointer(), stroke, breakAngles, frameCreated, + levelCreated, sLevel, id); + // la notifica viene gia fatta da addStroke! + // getApplication()->getCurrentTool()->getTool()->notifyImageChanged(); +} + +//--------------------------------------------------------------------------------------------------------- + +enum DrawOrder { OverAll = 0, UnderAll, PaletteOrder }; + +void getAboveStyleIdSet(int styleId, TPaletteP palette, + QSet &aboveStyles) { + if (!palette) return; + for (int p = 0; p < palette->getPageCount(); p++) { + TPalette::Page *page = palette->getPage(p); + for (int s = 0; s < page->getStyleCount(); s++) { + int tmpId = page->getStyleId(s); + if (tmpId == styleId) return; + if (tmpId != 0) aboveStyles.insert(tmpId); + } + } +} + +//========================================================================================================= + +double computeThickness(double pressure, const TDoublePairProperty &property, + bool isPath) { + if (isPath) return 0.0; + double t = pressure * pressure * pressure; + double thick0 = property.getValue().first; + double thick1 = property.getValue().second; + if (thick1 < 0.0001) thick0 = thick1 = 0.0; + return (thick0 + (thick1 - thick0) * t) * 0.5; +} + +} // namespace + +//=================================================================== +// +// ToonzVectorBrushTool +// +//----------------------------------------------------------------------------- + +ToonzVectorBrushTool::ToonzVectorBrushTool(std::string name, int targetType) + : TTool(name) + , m_thickness("Size", 0, 100, 0, 5) + , m_accuracy("Accuracy:", 1, 100, 20) + , m_smooth("Smooth:", 0, 50, 0) + , m_preset("Preset:") + , m_breakAngles("Break", true) + , m_pressure("Pressure", true) + , m_capStyle("Cap") + , m_joinStyle("Join") + , m_miterJoinLimit("Miter:", 0, 100, 4) + , m_rasterTrack(0) + , m_styleId(0) + , m_modifiedRegion() + , m_bluredBrush(0) + , m_active(false) + , m_enabled(false) + , m_isPrompting(false) + , m_firstTime(true) + , m_firstFrameRange(true) + , m_presetsLoaded(false) + , m_frameRange("Range:") + , m_snap("Snap", false) + , m_snapSensitivity("Sensitivity:") + , m_targetType(targetType) + , m_workingFrameId(TFrameId()) { + bind(targetType); + m_prop[0].bind(m_thickness); + m_prop[0].bind(m_accuracy); + m_prop[0].bind(m_smooth); + m_prop[0].bind(m_breakAngles); + m_prop[0].bind(m_pressure); + + m_prop[0].bind(m_frameRange); + m_frameRange.addValue(L"Off"); + m_frameRange.addValue(LINEAR_WSTR); + m_frameRange.addValue(EASEIN_WSTR); + m_frameRange.addValue(EASEOUT_WSTR); + m_frameRange.addValue(EASEINOUT_WSTR); + + m_prop[0].bind(m_snap); + + m_prop[0].bind(m_snapSensitivity); + m_snapSensitivity.addValue(LOW_WSTR); + m_snapSensitivity.addValue(MEDIUM_WSTR); + m_snapSensitivity.addValue(HIGH_WSTR); + + m_prop[0].bind(m_preset); + m_preset.addValue(CUSTOM_WSTR); + + m_prop[1].bind(m_capStyle); + m_capStyle.addValue(BUTT_WSTR, QString::fromStdWString(BUTT_WSTR)); + m_capStyle.addValue(ROUNDC_WSTR, QString::fromStdWString(ROUNDC_WSTR)); + m_capStyle.addValue(PROJECTING_WSTR, + QString::fromStdWString(PROJECTING_WSTR)); + + m_prop[1].bind(m_joinStyle); + m_joinStyle.addValue(MITER_WSTR, QString::fromStdWString(MITER_WSTR)); + m_joinStyle.addValue(ROUNDJ_WSTR, QString::fromStdWString(ROUNDJ_WSTR)); + m_joinStyle.addValue(BEVEL_WSTR, QString::fromStdWString(BEVEL_WSTR)); + + m_prop[1].bind(m_miterJoinLimit); + + m_breakAngles.setId("BreakSharpAngles"); + m_frameRange.setId("FrameRange"); + m_snap.setId("Snap"); + m_snapSensitivity.setId("SnapSensitivity"); + m_preset.setId("BrushPreset"); + m_pressure.setId("PressureSensitivity"); + m_capStyle.setId("Cap"); + m_joinStyle.setId("Join"); + m_miterJoinLimit.setId("Miter"); +} + +//------------------------------------------------------------------------------------------------------- + +ToolOptionsBox *ToonzVectorBrushTool::createOptionsBox() { + TPaletteHandle *currPalette = + TTool::getApplication()->getPaletteController()->getCurrentLevelPalette(); + ToolHandle *currTool = TTool::getApplication()->getCurrentTool(); + return new BrushToolOptionsBox(0, this, currPalette, currTool); +} + +//------------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::updateTranslation() { + m_thickness.setQStringName(tr("Size")); + m_accuracy.setQStringName(tr("Accuracy:")); + m_smooth.setQStringName(tr("Smooth:")); + m_preset.setQStringName(tr("Preset:")); + m_preset.setItemUIName(CUSTOM_WSTR, tr("")); + m_breakAngles.setQStringName(tr("Break")); + m_pressure.setQStringName(tr("Pressure")); + m_capStyle.setQStringName(tr("Cap")); + m_joinStyle.setQStringName(tr("Join")); + m_miterJoinLimit.setQStringName(tr("Miter:")); + m_frameRange.setQStringName(tr("Range:")); + m_snap.setQStringName(tr("Snap")); + m_snapSensitivity.setQStringName(""); + m_frameRange.setItemUIName(L"Off", tr("Off")); + m_frameRange.setItemUIName(LINEAR_WSTR, tr("Linear")); + m_frameRange.setItemUIName(EASEIN_WSTR, tr("In")); + m_frameRange.setItemUIName(EASEOUT_WSTR, tr("Out")); + m_frameRange.setItemUIName(EASEINOUT_WSTR, tr("In&Out")); + m_snapSensitivity.setItemUIName(LOW_WSTR, tr("Low")); + m_snapSensitivity.setItemUIName(MEDIUM_WSTR, tr("Med")); + m_snapSensitivity.setItemUIName(HIGH_WSTR, tr("High")); + m_capStyle.setItemUIName(BUTT_WSTR, tr("Butt cap")); + m_capStyle.setItemUIName(ROUNDC_WSTR, tr("Round cap")); + m_capStyle.setItemUIName(PROJECTING_WSTR, tr("Projecting cap")); + m_joinStyle.setItemUIName(MITER_WSTR, tr("Miter join")); + m_joinStyle.setItemUIName(ROUNDJ_WSTR, tr("Round join")); + m_joinStyle.setItemUIName(BEVEL_WSTR, tr("Bevel join")); +} + +//--------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::onActivate() { + if (m_firstTime) { + m_thickness.setValue( + TDoublePairProperty::Value(V_VectorBrushMinSize, V_VectorBrushMaxSize)); + + m_capStyle.setIndex(V_VectorCapStyle); + m_joinStyle.setIndex(V_VectorJoinStyle); + m_miterJoinLimit.setValue(V_VectorMiterValue); + m_breakAngles.setValue(V_BrushBreakSharpAngles ? 1 : 0); + m_accuracy.setValue(V_BrushAccuracy); + + m_pressure.setValue(V_BrushPressureSensitivity ? 1 : 0); + m_firstTime = false; + m_smooth.setValue(V_BrushSmooth); + + m_frameRange.setIndex(V_VectorBrushFrameRange); + m_snap.setValue(V_VectorBrushSnap); + m_snapSensitivity.setIndex(V_VectorBrushSnapSensitivity); + switch (V_VectorBrushSnapSensitivity) { + case 0: + m_minDistance2 = SNAPPING_LOW; + break; + case 1: + m_minDistance2 = SNAPPING_MEDIUM; + break; + case 2: + m_minDistance2 = SNAPPING_HIGH; + break; + } + } + resetFrameRange(); + // TODO:app->editImageOrSpline(); +} + +//-------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::onDeactivate() { + /*--- + * �h���b�O���Ƀc�[�����؂�ւ�����ꍇ�ɔ����AonDeactivate�ɂ�MouseRelease�Ɠ����������s�� + * ---*/ + if (m_tileSaver && !m_isPath) { + m_enabled = false; + } + m_workRas = TRaster32P(); + m_backupRas = TRasterCM32P(); + resetFrameRange(); +} + +//-------------------------------------------------------------------------------------------------- + +bool ToonzVectorBrushTool::preLeftButtonDown() { + touchImage(); + if (m_isFrameCreated) { + // When the xsheet frame is selected, whole viewer will be updated from + // SceneViewer::onXsheetChanged() on adding a new frame. + // We need to take care of a case when the level frame is selected. + if (m_application->getCurrentFrame()->isEditingLevel()) invalidate(); + } + return true; +} + +//-------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::leftButtonDown(const TPointD &pos, + const TMouseEvent &e) { + TTool::Application *app = TTool::getApplication(); + if (!app) return; + + int col = app->getCurrentColumn()->getColumnIndex(); + m_isPath = app->getCurrentObject()->isSpline(); + m_enabled = col >= 0 || m_isPath; + // todo: gestire autoenable + if (!m_enabled) return; + if (!m_isPath) { + m_currentColor = TPixel32::Black; + m_active = !!getImage(true); + if (!m_active) { + m_active = !!touchImage(); + } + if (!m_active) return; + + if (m_active) { + // nel caso che il colore corrente sia un cleanup/studiopalette color + // oppure il colore di un colorfield + m_styleId = app->getCurrentLevelStyleIndex(); + TColorStyle *cs = app->getCurrentLevelStyle(); + if (cs) { + TRasterStyleFx *rfx = cs ? cs->getRasterStyleFx() : 0; + m_active = + cs != 0 && (cs->isStrokeStyle() || (rfx && rfx->isInkStyle())); + m_currentColor = cs->getAverageColor(); + m_currentColor.m = 255; + } else { + m_styleId = 1; + m_currentColor = TPixel32::Black; + } + } + } else { + m_currentColor = TPixel32::Red; + m_active = true; + } + // assert(0<=m_styleId && m_styleId<2); + m_track.clear(); + double thickness = (m_pressure.getValue() || m_isPath) + ? computeThickness(e.m_pressure, m_thickness, m_isPath) + : m_thickness.getValue().second * 0.5; + + /*--- �X�g���[�N�̍ŏ���Max�T�C�Y�̉~���`����Ă��܂��s���h�~���� ---*/ + if (m_pressure.getValue() && e.m_pressure == 1.0) + thickness = m_thickness.getValue().first * 0.5; + m_currThickness = thickness; + m_smoothStroke.beginStroke(m_smooth.getValue()); + + if (m_foundFirstSnap) { + addTrackPoint(TThickPoint(m_firstSnapPoint, thickness), + getPixelSize() * getPixelSize()); + } else + addTrackPoint(TThickPoint(pos, thickness), getPixelSize() * getPixelSize()); + TRectD invalidateRect = m_track.getLastModifiedRegion(); + invalidate(invalidateRect.enlarge(2)); + + // updating m_brushPos is needed to refresh viewer properly + m_brushPos = m_mousePos = pos; +} + +//------------------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos, + const TMouseEvent &e) { + if (!m_enabled || !m_active) { + m_brushPos = m_mousePos = pos; + return; + } + double thickness = (m_pressure.getValue() || m_isPath) + ? computeThickness(e.m_pressure, m_thickness, m_isPath) + : m_thickness.getValue().second * 0.5; + + TRectD invalidateRect; + TPointD halfThick(m_maxThick * 0.5, m_maxThick * 0.5); + TPointD snapThick(6.0 * m_pixelSize, 6.0 * m_pixelSize); + + // In order to clear the previous brush tip + invalidateRect += TRectD(m_brushPos - halfThick, m_brushPos + halfThick); + + // In order to clear the previous snap indicator + if (m_foundLastSnap) + invalidateRect += + TRectD(m_lastSnapPoint - snapThick, m_lastSnapPoint + snapThick); + + m_currThickness = thickness; + + m_mousePos = pos; + m_lastSnapPoint = pos; + m_foundLastSnap = false; + m_foundFirstSnap = false; + m_snapSelf = false; + m_altPressed = e.isAltPressed() && !e.isCtrlPressed(); + + checkStrokeSnapping(false, m_altPressed); + checkGuideSnapping(false, m_altPressed); + m_brushPos = m_lastSnapPoint; + + if (m_foundLastSnap) + invalidateRect += + TRectD(m_lastSnapPoint - snapThick, m_lastSnapPoint + snapThick); + + if (e.isShiftPressed()) { + m_smoothStroke.clearPoints(); + m_track.add(TThickPoint(m_brushPos, thickness), + getPixelSize() * getPixelSize()); + m_track.removeMiddlePoints(); + invalidateRect += m_track.getModifiedRegion(); + } else if (m_dragDraw) { + addTrackPoint(TThickPoint(pos, thickness), getPixelSize() * getPixelSize()); + invalidateRect += m_track.getLastModifiedRegion(); + } + + // In order to draw the current brush tip + invalidateRect += TRectD(m_brushPos - halfThick, m_brushPos + halfThick); + + if (!invalidateRect.isEmpty()) { + // for motion path, call the invalidate function directry to ignore dpi of + // the current level + if (m_isPath) + m_viewer->GLInvalidateRect(invalidateRect.enlarge(2)); + else + invalidate(invalidateRect.enlarge(2)); + } +} + +//--------------------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::leftButtonUp(const TPointD &pos, + const TMouseEvent &e) { + bool isValid = m_enabled && m_active; + m_enabled = false; + + if (!isValid) { + // in case the current frame is moved to empty cell while dragging + if (!m_track.isEmpty()) { + m_track.clear(); + invalidate(); + } + return; + } + + if (m_isPath) { + double error = 20.0 * getPixelSize(); + + TStroke *stroke; + if (e.isShiftPressed()) { + m_track.removeMiddlePoints(); + stroke = m_track.makeStroke(0); + } else { + flushTrackPoint(); + stroke = m_track.makeStroke(error); + } + int points = stroke->getControlPointCount(); + + TVectorImageP vi = getImage(true); + struct Cleanup { + ToonzVectorBrushTool *m_this; + ~Cleanup() { m_this->m_track.clear(), m_this->invalidate(); } + } cleanup = {this}; + + if (!isJustCreatedSpline(vi.getPointer())) { + m_isPrompting = true; + + QString question("Are you sure you want to replace the motion path?"); + int ret = + DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"), 0); + + m_isPrompting = false; + + if (ret == 2 || ret == 0) return; + } + + QMutexLocker lock(vi->getMutex()); + + TUndo *undo = + new UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline()); + + while (vi->getStrokeCount() > 0) vi->deleteStroke(0); + vi->addStroke(stroke, false); + + notifyImageChanged(); + TUndoManager::manager()->add(undo); + + return; + } + + TVectorImageP vi = getImage(true); + if (m_track.isEmpty()) { + m_styleId = 0; + m_track.clear(); + return; + } + + if (vi && (m_snap.getValue() != m_altPressed) && m_foundLastSnap) { + addTrackPoint(TThickPoint(m_lastSnapPoint, m_currThickness), + getPixelSize() * getPixelSize()); + } + m_strokeIndex1 = -1; + m_strokeIndex2 = -1; + m_w1 = -1; + m_w2 = -2; + m_foundFirstSnap = false; + m_foundLastSnap = false; + + m_track.filterPoints(); + double error = 30.0 / (1 + 0.5 * m_accuracy.getValue()); + error *= getPixelSize(); + + TStroke *stroke; + if (e.isShiftPressed()) { + m_track.removeMiddlePoints(); + stroke = m_track.makeStroke(0); + } else { + flushTrackPoint(); + stroke = m_track.makeStroke(error); + } + stroke->setStyle(m_styleId); + { + TStroke::OutlineOptions &options = stroke->outlineOptions(); + options.m_capStyle = m_capStyle.getIndex(); + options.m_joinStyle = m_joinStyle.getIndex(); + options.m_miterUpper = m_miterJoinLimit.getValue(); + } + m_styleId = 0; + + QMutexLocker lock(vi->getMutex()); + if (stroke->getControlPointCount() == 3 && + stroke->getControlPoint(0) != + stroke->getControlPoint(2)) // gli stroke con solo 1 chunk vengono + // fatti dal tape tool...e devono venir + // riconosciuti come speciali di + // autoclose proprio dal fatto che + // hanno 1 solo chunk. + stroke->insertControlPoints(0.5); + if (m_frameRange.getIndex()) { + if (m_firstFrameId == -1) { + m_firstStroke = new TStroke(*stroke); + m_firstFrameId = getFrameId(); + TTool::Application *application = TTool::getApplication(); + if (application) { + m_col = application->getCurrentColumn()->getColumnIndex(); + m_firstFrame = application->getCurrentFrame()->getFrame(); + } + m_rangeTrack = m_track; + if (m_firstFrameRange) { + m_veryFirstCol = m_col; + m_veryFirstFrame = m_firstFrame; + m_veryFirstFrameId = m_firstFrameId; + } + } else if (m_firstFrameId == getFrameId()) { + if (m_firstStroke) { + delete m_firstStroke; + m_firstStroke = 0; + } + m_firstStroke = new TStroke(*stroke); + m_rangeTrack = m_track; + } else { + TFrameId currentId = getFrameId(); + int curCol = 0, curFrame = 0; + TTool::Application *application = TTool::getApplication(); + if (application) { + curCol = application->getCurrentColumn()->getColumnIndex(); + curFrame = application->getCurrentFrame()->getFrame(); + } + bool success = + doFrameRangeStrokes(m_firstFrameId, m_firstStroke, getFrameId(), + stroke, m_firstFrameRange); + if (e.isCtrlPressed()) { + if (application) { + if (m_firstFrameId > currentId) { + if (application->getCurrentFrame()->isEditingScene()) { + application->getCurrentColumn()->setColumnIndex(curCol); + application->getCurrentFrame()->setFrame(curFrame); + } else + application->getCurrentFrame()->setFid(currentId); + } + } + resetFrameRange(); + m_firstStroke = new TStroke(*stroke); + m_rangeTrack = m_track; + m_firstFrameId = currentId; + m_firstFrameRange = false; + } + + if (application && !e.isCtrlPressed()) { + if (application->getCurrentFrame()->isEditingScene()) { + application->getCurrentColumn()->setColumnIndex(m_veryFirstCol); + application->getCurrentFrame()->setFrame(m_veryFirstFrame); + } else + application->getCurrentFrame()->setFid(m_veryFirstFrameId); + } + + if (!e.isCtrlPressed()) { + resetFrameRange(); + } + } + invalidate(); + } else { + if (m_snapSelf) { + stroke->setSelfLoop(true); + m_snapSelf = false; + } + addStrokeToImage(getApplication(), vi, stroke, m_breakAngles.getValue(), + m_isFrameCreated, m_isLevelCreated); + TRectD bbox = stroke->getBBox().enlarge(2) + m_track.getModifiedRegion(); + invalidate(); // should use bbox? + } + assert(stroke); + m_track.clear(); + m_altPressed = false; +} + +//-------------------------------------------------------------------------------------------------- + +bool ToonzVectorBrushTool::keyDown(QKeyEvent *event) { + if (event->key() == Qt::Key_Escape) { + resetFrameRange(); + } + return false; +} + +//-------------------------------------------------------------------------------------------------- + +bool ToonzVectorBrushTool::doFrameRangeStrokes(TFrameId firstFrameId, + TStroke *firstStroke, + TFrameId lastFrameId, + TStroke *lastStroke, + bool drawFirstStroke) { + TXshSimpleLevel *sl = + TTool::getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(); + TStroke *first = new TStroke(); + TStroke *last = new TStroke(); + TVectorImageP firstImage = new TVectorImage(); + TVectorImageP lastImage = new TVectorImage(); + + *first = *firstStroke; + *last = *lastStroke; + bool swapped = false; + if (firstFrameId > lastFrameId) { + std::swap(firstFrameId, lastFrameId); + *first = *lastStroke; + *last = *firstStroke; + swapped = true; + } + + firstImage->addStroke(first, false); + lastImage->addStroke(last, false); + assert(firstFrameId <= lastFrameId); + + std::vector allFids; + sl->getFids(allFids); + std::vector::iterator i0 = allFids.begin(); + while (i0 != allFids.end() && *i0 < firstFrameId) i0++; + if (i0 == allFids.end()) return false; + std::vector::iterator i1 = i0; + while (i1 != allFids.end() && *i1 <= lastFrameId) i1++; + assert(i0 < i1); + std::vector fids(i0, i1); + int m = fids.size(); + assert(m > 0); + + TUndoManager::manager()->beginBlock(); + for (int i = 0; i < m; ++i) { + TFrameId fid = fids[i]; + assert(firstFrameId <= fid && fid <= lastFrameId); + + // This is an attempt to divide the tween evenly + double t = m > 1 ? (double)i / (double)(m - 1) : 0.5; + double s = t; + switch (m_frameRange.getIndex()) { + case 1: // LINEAR_WSTR + break; + case 2: // EASEIN_WSTR + s = t * t; + break; // s'(0) = 0 + case 3: // EASEOUT_WSTR + s = t * (2 - t); + break; // s'(1) = 0 + case 4: // EASEINOUT_WSTR: + s = t * t * (3 - 2 * t); + break; // s'(0) = s'(1) = 0 + } + + TTool::Application *app = TTool::getApplication(); + if (app) { + if (app->getCurrentFrame()->isEditingScene()) + app->getCurrentFrame()->setFrame(fid.getNumber() - 1); + else + app->getCurrentFrame()->setFid(fid); + } + + TVectorImageP img = sl->getFrame(fid, true); + if (t == 0) { + if (!swapped && !drawFirstStroke) { + } else + addStrokeToImage(getApplication(), img, firstImage->getStroke(0), + m_breakAngles.getValue(), m_isFrameCreated, + m_isLevelCreated, sl, fid); + } else if (t == 1) { + if (swapped && !drawFirstStroke) { + } else + addStrokeToImage(getApplication(), img, lastImage->getStroke(0), + m_breakAngles.getValue(), m_isFrameCreated, + m_isLevelCreated, sl, fid); + } else { + assert(firstImage->getStrokeCount() == 1); + assert(lastImage->getStrokeCount() == 1); + TVectorImageP vi = TInbetween(firstImage, lastImage).tween(s); + assert(vi->getStrokeCount() == 1); + addStrokeToImage(getApplication(), img, vi->getStroke(0), + m_breakAngles.getValue(), m_isFrameCreated, + m_isLevelCreated, sl, fid); + } + } + TUndoManager::manager()->endBlock(); + notifyImageChanged(); + return true; +} + +//-------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::addTrackPoint(const TThickPoint &point, + double pixelSize2) { + m_smoothStroke.addPoint(point); + std::vector pts; + m_smoothStroke.getSmoothPoints(pts); + for (size_t i = 0; i < pts.size(); ++i) { + m_track.add(pts[i], pixelSize2); + } +} + +//-------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::flushTrackPoint() { + m_smoothStroke.endStroke(); + std::vector pts; + m_smoothStroke.getSmoothPoints(pts); + double pixelSize2 = getPixelSize() * getPixelSize(); + for (size_t i = 0; i < pts.size(); ++i) { + m_track.add(pts[i], pixelSize2); + } +} + +//--------------------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::mouseMove(const TPointD &pos, const TMouseEvent &e) { + qApp->processEvents(QEventLoop::ExcludeUserInputEvents); + + struct Locals { + ToonzVectorBrushTool *m_this; + + void setValue(TDoublePairProperty &prop, + const TDoublePairProperty::Value &value) { + prop.setValue(value); + + m_this->onPropertyChanged(prop.getName()); + TTool::getApplication()->getCurrentTool()->notifyToolChanged(); + } + + void addMinMax(TDoublePairProperty &prop, double add) { + if (add == 0.0) return; + const TDoublePairProperty::Range &range = prop.getRange(); + + TDoublePairProperty::Value value = prop.getValue(); + value.first = tcrop(value.first + add, range.first, range.second); + value.second = tcrop(value.second + add, range.first, range.second); + + setValue(prop, value); + } + + void addMinMaxSeparate(TDoublePairProperty &prop, double min, double max) { + if (min == 0.0 && max == 0.0) return; + const TDoublePairProperty::Range &range = prop.getRange(); + + TDoublePairProperty::Value value = prop.getValue(); + value.first += min; + value.second += max; + if (value.first > value.second) value.first = value.second; + value.first = tcrop(value.first, range.first, range.second); + value.second = tcrop(value.second, range.first, range.second); + + setValue(prop, value); + } + + } locals = {this}; + + TPointD halfThick(m_maxThick * 0.5, m_maxThick * 0.5); + TRectD invalidateRect(m_brushPos - halfThick, m_brushPos + halfThick); + + if (e.isCtrlPressed() && e.isAltPressed() && !e.isShiftPressed()) { + const TPointD &diff = pos - m_mousePos; + double max = diff.x / 2; + double min = diff.y / 2; + + locals.addMinMaxSeparate(m_thickness, min, max); + + double radius = m_thickness.getValue().second * 0.5; + invalidateRect += TRectD(m_brushPos - TPointD(radius, radius), + m_brushPos + TPointD(radius, radius)); + + } else { + m_mousePos = pos; + m_brushPos = pos; + + TPointD snapThick(6.0 * m_pixelSize, 6.0 * m_pixelSize); + // In order to clear the previous snap indicator + if (m_foundFirstSnap) + invalidateRect += + TRectD(m_firstSnapPoint - snapThick, m_firstSnapPoint + snapThick); + + m_firstSnapPoint = pos; + m_foundFirstSnap = false; + m_altPressed = e.isAltPressed() && !e.isCtrlPressed(); + checkStrokeSnapping(true, m_altPressed); + checkGuideSnapping(true, m_altPressed); + m_brushPos = m_firstSnapPoint; + // In order to draw the snap indicator + if (m_foundFirstSnap) + invalidateRect += + TRectD(m_firstSnapPoint - snapThick, m_firstSnapPoint + snapThick); + + invalidateRect += TRectD(pos - halfThick, pos + halfThick); + } + + invalidate(invalidateRect.enlarge(2)); + + if (m_minThick == 0 && m_maxThick == 0) { + m_minThick = m_thickness.getValue().first; + m_maxThick = m_thickness.getValue().second; + } +} + +//------------------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::checkStrokeSnapping(bool beforeMousePress, + bool invertCheck) { + if (Preferences::instance()->getVectorSnappingTarget() == 1) return; + + TVectorImageP vi(getImage(false)); + bool checkSnap = m_snap.getValue(); + if (invertCheck) checkSnap = !checkSnap; + if (vi && checkSnap) { + m_dragDraw = true; + double minDistance2 = m_minDistance2; + if (beforeMousePress) + m_strokeIndex1 = -1; + else + m_strokeIndex2 = -1; + int i, strokeNumber = vi->getStrokeCount(); + TStroke *stroke; + double distance2, outW; + bool snapFound = false; + TThickPoint point1; + + for (i = 0; i < strokeNumber; i++) { + stroke = vi->getStroke(i); + if (stroke->getNearestW(m_mousePos, outW, distance2) && + distance2 < minDistance2) { + minDistance2 = distance2; + beforeMousePress ? m_strokeIndex1 = i : m_strokeIndex2 = i; + if (areAlmostEqual(outW, 0.0, 1e-3)) + beforeMousePress ? m_w1 = 0.0 : m_w2 = 0.0; + else if (areAlmostEqual(outW, 1.0, 1e-3)) + beforeMousePress ? m_w1 = 1.0 : m_w2 = 1.0; + else + beforeMousePress ? m_w1 = outW : m_w2 = outW; + + beforeMousePress ? point1 = stroke->getPoint(m_w1) + : point1 = stroke->getPoint(m_w2); + snapFound = true; + } + } + // compare to first point of current stroke + if (beforeMousePress && snapFound) { + m_firstSnapPoint = TPointD(point1.x, point1.y); + m_foundFirstSnap = true; + } else if (!beforeMousePress) { + if (!snapFound) { + TPointD tempPoint = m_track.getFirstPoint(); + double distanceFromStart = tdistance2(m_mousePos, tempPoint); + + if (distanceFromStart < m_minDistance2) { + point1 = tempPoint; + distance2 = distanceFromStart; + snapFound = true; + m_snapSelf = true; + } + } + if (snapFound) { + m_lastSnapPoint = TPointD(point1.x, point1.y); + m_foundLastSnap = true; + if (distance2 < 2.0) m_dragDraw = false; + } + } + } +} + +//------------------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::checkGuideSnapping(bool beforeMousePress, + bool invertCheck) { + if (Preferences::instance()->getVectorSnappingTarget() == 0) return; + bool foundSnap; + TPointD snapPoint; + beforeMousePress ? foundSnap = m_foundFirstSnap : foundSnap = m_foundLastSnap; + beforeMousePress ? snapPoint = m_firstSnapPoint : snapPoint = m_lastSnapPoint; + + bool checkSnap = m_snap.getValue(); + if (invertCheck) checkSnap = !checkSnap; + + if (checkSnap) { + // check guide snapping + int vGuideCount = 0, hGuideCount = 0; + double guideDistance = sqrt(m_minDistance2); + TTool::Viewer *viewer = getViewer(); + if (viewer) { + vGuideCount = viewer->getVGuideCount(); + hGuideCount = viewer->getHGuideCount(); + } + double distanceToVGuide = -1.0, distanceToHGuide = -1.0; + double vGuide, hGuide; + bool useGuides = false; + if (vGuideCount) { + for (int j = 0; j < vGuideCount; j++) { + double guide = viewer->getVGuide(j); + double tempDistance = abs(guide - m_mousePos.y); + if (tempDistance < guideDistance && + (distanceToVGuide < 0 || tempDistance < distanceToVGuide)) { + distanceToVGuide = tempDistance; + vGuide = guide; + useGuides = true; + } + } + } + if (hGuideCount) { + for (int j = 0; j < hGuideCount; j++) { + double guide = viewer->getHGuide(j); + double tempDistance = abs(guide - m_mousePos.x); + if (tempDistance < guideDistance && + (distanceToHGuide < 0 || tempDistance < distanceToHGuide)) { + distanceToHGuide = tempDistance; + hGuide = guide; + useGuides = true; + } + } + } + if (useGuides && foundSnap) { + double currYDistance = abs(snapPoint.y - m_mousePos.y); + double currXDistance = abs(snapPoint.x - m_mousePos.x); + double hypotenuse = + sqrt(pow(currYDistance, 2.0) + pow(currXDistance, 2.0)); + if ((distanceToVGuide >= 0 && distanceToVGuide < hypotenuse) || + (distanceToHGuide >= 0 && distanceToHGuide < hypotenuse)) { + useGuides = true; + m_snapSelf = false; + } else + useGuides = false; + } + if (useGuides) { + assert(distanceToHGuide >= 0 || distanceToVGuide >= 0); + if (distanceToHGuide < 0 || + (distanceToVGuide <= distanceToHGuide && distanceToVGuide >= 0)) { + snapPoint.y = vGuide; + snapPoint.x = m_mousePos.x; + + } else { + snapPoint.y = m_mousePos.y; + snapPoint.x = hGuide; + } + beforeMousePress ? m_foundFirstSnap = true : m_foundLastSnap = true; + beforeMousePress ? m_firstSnapPoint = snapPoint + : m_lastSnapPoint = snapPoint; + } + } +} + +//------------------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::draw() { + /*--�V���[�g�J�b�g�ł̃c�[���؂�ւ����ɐԓ_���`�����̂�h�~����--*/ + if (m_minThick == 0 && m_maxThick == 0 && + !Preferences::instance()->getShow0ThickLines()) + return; + + TImageP img = getImage(false, 1); + + // Draw track + tglColor(m_isPrompting ? TPixel32::Green : m_currentColor); + m_track.drawAllFragments(); + + // snapping + TVectorImageP vi = img; + if (m_snap.getValue() != m_altPressed) { + m_pixelSize = getPixelSize(); + double thick = 6.0 * m_pixelSize; + if (m_foundFirstSnap) { + tglColor(TPixelD(0.1, 0.9, 0.1)); + tglDrawCircle(m_firstSnapPoint, thick); + } + + TThickPoint point2; + + if (m_foundLastSnap) { + tglColor(TPixelD(0.1, 0.9, 0.1)); + tglDrawCircle(m_lastSnapPoint, thick); + } + } + + // frame range + if (m_firstStroke) { + glColor3d(1.0, 0.0, 0.0); + m_rangeTrack.drawAllFragments(); + glColor3d(0.0, 0.6, 0.0); + TPointD firstPoint = m_rangeTrack.getFirstPoint(); + TPointD topLeftCorner = TPointD(firstPoint.x - 5, firstPoint.y - 5); + TPointD topRightCorner = TPointD(firstPoint.x + 5, firstPoint.y - 5); + TPointD bottomLeftCorner = TPointD(firstPoint.x - 5, firstPoint.y + 5); + TPointD bottomRightCorner = TPointD(firstPoint.x + 5, firstPoint.y + 5); + tglDrawSegment(topLeftCorner, bottomRightCorner); + tglDrawSegment(topRightCorner, bottomLeftCorner); + } + + if (getApplication()->getCurrentObject()->isSpline()) return; + + // If toggled off, don't draw brush outline + if (!Preferences::instance()->isCursorOutlineEnabled()) return; + + // Draw the brush outline - change color when the Ink / Paint check is + // activated + if ((ToonzCheck::instance()->getChecks() & ToonzCheck::eInk) || + (ToonzCheck::instance()->getChecks() & ToonzCheck::ePaint) || + (ToonzCheck::instance()->getChecks() & ToonzCheck::eInk1)) + glColor3d(0.5, 0.8, 0.8); + // normally draw in red + else + glColor3d(1.0, 0.0, 0.0); + + tglDrawCircle(m_brushPos, 0.5 * m_minThick); + tglDrawCircle(m_brushPos, 0.5 * m_maxThick); +} + +//-------------------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::onEnter() { + TImageP img = getImage(false); + + m_minThick = m_thickness.getValue().first; + m_maxThick = m_thickness.getValue().second; + + Application *app = getApplication(); + + m_styleId = app->getCurrentLevelStyleIndex(); + TColorStyle *cs = app->getCurrentLevelStyle(); + if (cs) { + TRasterStyleFx *rfx = cs->getRasterStyleFx(); + m_active = cs->isStrokeStyle() || (rfx && rfx->isInkStyle()); + m_currentColor = cs->getAverageColor(); + m_currentColor.m = 255; + } else { + m_currentColor = TPixel32::Black; + } + m_active = img; +} + +//---------------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::onLeave() { + m_minThick = 0; + m_maxThick = 0; +} + +//---------------------------------------------------------------------------------------------------------- + +TPropertyGroup *ToonzVectorBrushTool::getProperties(int idx) { + if (!m_presetsLoaded) initPresets(); + + return &m_prop[idx]; +} + +//------------------------------------------------------------------ + +void ToonzVectorBrushTool::resetFrameRange() { + m_rangeTrack.clear(); + m_firstFrameId = -1; + if (m_firstStroke) { + delete m_firstStroke; + m_firstStroke = 0; + } + m_firstFrameRange = true; +} + +//------------------------------------------------------------------ + +bool ToonzVectorBrushTool::onPropertyChanged(std::string propertyName) { + // Set the following to true whenever a different piece of interface must + // be refreshed - done once at the end. + bool notifyTool = false; + + /*--- �ύX���ꂽProperty�ɍ��킹�ď����𕪂��� ---*/ + + /*--- determine which type of brush to be modified ---*/ + if (propertyName == m_thickness.getName()) { + V_VectorBrushMinSize = m_thickness.getValue().first; + V_VectorBrushMaxSize = m_thickness.getValue().second; + m_minThick = m_thickness.getValue().first; + m_maxThick = m_thickness.getValue().second; + } else if (propertyName == m_accuracy.getName()) { + V_BrushAccuracy = m_accuracy.getValue(); + } else if (propertyName == m_smooth.getName()) { + V_BrushSmooth = m_smooth.getValue(); + } else if (propertyName == m_preset.getName()) { + loadPreset(); + notifyTool = true; + } else if (propertyName == m_breakAngles.getName()) { + V_BrushBreakSharpAngles = m_breakAngles.getValue(); + } else if (propertyName == m_pressure.getName()) { + V_BrushPressureSensitivity = m_pressure.getValue(); + } else if (propertyName == m_capStyle.getName()) { + V_VectorCapStyle = m_capStyle.getIndex(); + } else if (propertyName == m_joinStyle.getName()) { + V_VectorJoinStyle = m_joinStyle.getIndex(); + } else if (propertyName == m_miterJoinLimit.getName()) { + V_VectorMiterValue = m_miterJoinLimit.getValue(); + } else if (propertyName == m_frameRange.getName()) { + int index = m_frameRange.getIndex(); + V_VectorBrushFrameRange = index; + if (index == 0) resetFrameRange(); + } else if (propertyName == m_snap.getName()) { + V_VectorBrushSnap = m_snap.getValue(); + } else if (propertyName == m_snapSensitivity.getName()) { + int index = m_snapSensitivity.getIndex(); + V_VectorBrushSnapSensitivity = index; + switch (index) { + case 0: + m_minDistance2 = SNAPPING_LOW; + break; + case 1: + m_minDistance2 = SNAPPING_MEDIUM; + break; + case 2: + m_minDistance2 = SNAPPING_HIGH; + break; + } + } + + if (propertyName == m_joinStyle.getName()) notifyTool = true; + + if (propertyName != m_preset.getName() && + m_preset.getValue() != CUSTOM_WSTR) { + m_preset.setValue(CUSTOM_WSTR); + notifyTool = true; + } + + if (notifyTool) getApplication()->getCurrentTool()->notifyToolChanged(); + + return true; +} + +//------------------------------------------------------------------ + +void ToonzVectorBrushTool::initPresets() { + if (!m_presetsLoaded) { + // If necessary, load the presets from file + m_presetsLoaded = true; + m_presetsManager.load(TEnv::getConfigDir() + "brush_vector.txt"); + } + + // Rebuild the presets property entries + const std::set &presets = m_presetsManager.presets(); + + m_preset.deleteAllValues(); + m_preset.addValue(CUSTOM_WSTR); + m_preset.setItemUIName(CUSTOM_WSTR, tr("")); + + std::set::const_iterator it, end = presets.end(); + for (it = presets.begin(); it != end; ++it) m_preset.addValue(it->m_name); +} + +//---------------------------------------------------------------------------------------------------------- + +void ToonzVectorBrushTool::loadPreset() { + const std::set &presets = m_presetsManager.presets(); + std::set::const_iterator it; + + it = presets.find(VectorBrushData(m_preset.getValue())); + if (it == presets.end()) return; + + const VectorBrushData &preset = *it; + + try // Don't bother with RangeErrors + { + m_thickness.setValue( + TDoublePairProperty::Value(preset.m_min, preset.m_max)); + m_accuracy.setValue(preset.m_acc, true); + m_smooth.setValue(preset.m_smooth, true); + m_breakAngles.setValue(preset.m_breakAngles); + m_pressure.setValue(preset.m_pressure); + m_capStyle.setIndex(preset.m_cap); + m_joinStyle.setIndex(preset.m_join); + m_miterJoinLimit.setValue(preset.m_miter); + + } catch (...) { + } +} + +//------------------------------------------------------------------ + +void ToonzVectorBrushTool::addPreset(QString name) { + // Build the preset + VectorBrushData preset(name.toStdWString()); + + preset.m_min = m_thickness.getValue().first; + preset.m_max = m_thickness.getValue().second; + + preset.m_acc = m_accuracy.getValue(); + preset.m_smooth = m_smooth.getValue(); + preset.m_breakAngles = m_breakAngles.getValue(); + preset.m_pressure = m_pressure.getValue(); + preset.m_cap = m_capStyle.getIndex(); + preset.m_join = m_joinStyle.getIndex(); + preset.m_miter = m_miterJoinLimit.getValue(); + + // Pass the preset to the manager + m_presetsManager.addPreset(preset); + + // Reinitialize the associated preset enum + initPresets(); + + // Set the value to the specified one + m_preset.setValue(preset.m_name); +} + +//------------------------------------------------------------------ + +void ToonzVectorBrushTool::removePreset() { + std::wstring name(m_preset.getValue()); + if (name == CUSTOM_WSTR) return; + + m_presetsManager.removePreset(name); + initPresets(); + + // No parameter change, and set the preset value to custom + m_preset.setValue(CUSTOM_WSTR); +} + +//------------------------------------------------------------------ +/*! Brush�APaintBrush�AEraserTool��PencilMode�̂Ƃ���True��Ԃ� +*/ +bool ToonzVectorBrushTool::isPencilModeActive() { return false; } + +//========================================================================================================== + +// Tools instantiation + +ToonzVectorBrushTool vectorPencil("T_Brush", + TTool::Vectors | TTool::EmptyTarget); + +//******************************************************************************* +// Brush Data implementation +//******************************************************************************* + +VectorBrushData::VectorBrushData() + : m_name() + , m_min(0.0) + , m_max(0.0) + , m_acc(0.0) + , m_smooth(0.0) + , m_breakAngles(false) + , m_pressure(false) + , m_cap(0) + , m_join(0) + , m_miter(0) {} + +//---------------------------------------------------------------------------------------------------------- + +VectorBrushData::VectorBrushData(const std::wstring &name) + : m_name(name) + , m_min(0.0) + , m_max(0.0) + , m_acc(0.0) + , m_smooth(0.0) + , m_breakAngles(false) + , m_pressure(false) + , m_cap(0) + , m_join(0) + , m_miter(0) {} + +//---------------------------------------------------------------------------------------------------------- + +void VectorBrushData::saveData(TOStream &os) { + os.openChild("Name"); + os << m_name; + os.closeChild(); + os.openChild("Thickness"); + os << m_min << m_max; + os.closeChild(); + os.openChild("Accuracy"); + os << m_acc; + os.closeChild(); + os.openChild("Smooth"); + os << m_smooth; + os.closeChild(); + os.openChild("Break_Sharp_Angles"); + os << (int)m_breakAngles; + os.closeChild(); + os.openChild("Pressure_Sensitivity"); + os << (int)m_pressure; + os.closeChild(); + os.openChild("Cap"); + os << m_cap; + os.closeChild(); + os.openChild("Join"); + os << m_join; + os.closeChild(); + os.openChild("Miter"); + os << m_miter; + os.closeChild(); +} + +//---------------------------------------------------------------------------------------------------------- + +void VectorBrushData::loadData(TIStream &is) { + std::string tagName; + int val; + + while (is.matchTag(tagName)) { + if (tagName == "Name") + is >> m_name, is.matchEndTag(); + else if (tagName == "Thickness") + is >> m_min >> m_max, is.matchEndTag(); + else if (tagName == "Accuracy") + is >> m_acc, is.matchEndTag(); + else if (tagName == "Smooth") + is >> m_smooth, is.matchEndTag(); + else if (tagName == "Break_Sharp_Angles") + is >> val, m_breakAngles = val, is.matchEndTag(); + else if (tagName == "Pressure_Sensitivity") + is >> val, m_pressure = val, is.matchEndTag(); + else if (tagName == "Cap") + is >> m_cap, is.matchEndTag(); + else if (tagName == "Join") + is >> m_join, is.matchEndTag(); + else if (tagName == "Miter") + is >> m_miter, is.matchEndTag(); + else + is.skipCurrentTag(); + } +} + +//---------------------------------------------------------------------------------------------------------- + +PERSIST_IDENTIFIER(VectorBrushData, "VectorBrushData"); + +//******************************************************************************* +// Brush Preset Manager implementation +//******************************************************************************* + +void VectorBrushPresetManager::load(const TFilePath &fp) { + m_fp = fp; + + std::string tagName; + VectorBrushData data; + + TIStream is(m_fp); + try { + while (is.matchTag(tagName)) { + if (tagName == "version") { + VersionNumber version; + is >> version.first >> version.second; + + is.setVersion(version); + is.matchEndTag(); + } else if (tagName == "brushes") { + while (is.matchTag(tagName)) { + if (tagName == "brush") { + is >> data, m_presets.insert(data); + is.matchEndTag(); + } else + is.skipCurrentTag(); + } + + is.matchEndTag(); + } else + is.skipCurrentTag(); + } + } catch (...) { + } +} + +//------------------------------------------------------------------ + +void VectorBrushPresetManager::save() { + TOStream os(m_fp); + + os.openChild("version"); + os << 1 << 20; + os.closeChild(); + + os.openChild("brushes"); + + std::set::iterator it, end = m_presets.end(); + for (it = m_presets.begin(); it != end; ++it) { + os.openChild("brush"); + os << (TPersist &)*it; + os.closeChild(); + } + + os.closeChild(); +} + +//------------------------------------------------------------------ + +void VectorBrushPresetManager::addPreset(const VectorBrushData &data) { + m_presets.erase(data); // Overwriting insertion + m_presets.insert(data); + save(); +} + +//------------------------------------------------------------------ + +void VectorBrushPresetManager::removePreset(const std::wstring &name) { + m_presets.erase(VectorBrushData(name)); + save(); +} diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.h b/toonz/sources/tnztools/toonzvectorbrushtool.h new file mode 100644 index 0000000..887da39 --- /dev/null +++ b/toonz/sources/tnztools/toonzvectorbrushtool.h @@ -0,0 +1,197 @@ +#pragma once + +#ifndef TOONZVECTORBRUSHTOOL_H +#define TOONZVECTORBRUSHTOOL_H + +#include "tgeometry.h" +#include "tproperty.h" +#include "trasterimage.h" +#include "ttoonzimage.h" +#include "tstroke.h" +#include "toonz/strokegenerator.h" + +#include "tools/tool.h" +#include "tools/cursors.h" + +#include "toonzrasterbrushtool.h" + +#include +#include + +//-------------------------------------------------------------- + +// Forward declarations + +class TTileSetCM32; +class TTileSaverCM32; +class RasterStrokeGenerator; +class BluredBrush; + +//-------------------------------------------------------------- + +//************************************************************************ +// Brush Data declaration +//************************************************************************ + +struct VectorBrushData final : public TPersist { + PERSIST_DECLARATION(VectorBrushData) + // frameRange, snapSensitivity and snap are not included + // Those options are not really a part of the brush settings, + // just the overall tool. + + std::wstring m_name; + double m_min, m_max, m_acc, m_smooth; + bool m_breakAngles, m_pressure; + int m_cap, m_join, m_miter; + + VectorBrushData(); + VectorBrushData(const std::wstring &name); + + bool operator<(const VectorBrushData &other) const { + return m_name < other.m_name; + } + + void saveData(TOStream &os) override; + void loadData(TIStream &is) override; +}; + +//************************************************************************ +// Brush Preset Manager declaration +//************************************************************************ + +class VectorBrushPresetManager { + TFilePath m_fp; //!< Presets file path + std::set m_presets; //!< Current presets container + +public: + VectorBrushPresetManager() {} + + void load(const TFilePath &fp); + void save(); + + const TFilePath &path() { return m_fp; }; + const std::set &presets() const { return m_presets; } + + void addPreset(const VectorBrushData &data); + void removePreset(const std::wstring &name); +}; + +//************************************************************************ +// Brush Tool declaration +//************************************************************************ + +class ToonzVectorBrushTool final : public TTool { + Q_DECLARE_TR_FUNCTIONS(BrushTool) + +public: + ToonzVectorBrushTool(std::string name, int targetType); + + ToolType getToolType() const override { return TTool::LevelWriteTool; } + + ToolOptionsBox *createOptionsBox() override; + + void updateTranslation() override; + + void onActivate() override; + void onDeactivate() override; + + bool preLeftButtonDown() override; + void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override; + void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override; + void leftButtonUp(const TPointD &pos, const TMouseEvent &e) override; + void mouseMove(const TPointD &pos, const TMouseEvent &e) override; + bool keyDown(QKeyEvent *event) override; + + void draw() override; + + void onEnter() override; + void onLeave() override; + + int getCursorId() const override { return ToolCursor::PenCursor; } + + TPropertyGroup *getProperties(int targetType) override; + bool onPropertyChanged(std::string propertyName) override; + void resetFrameRange(); + + void initPresets(); + void loadPreset(); + void addPreset(QString name); + void removePreset(); + + // return true if the pencil mode is active in the Brush / PaintBrush / Eraser + // Tools. + bool isPencilModeActive() override; + + void addTrackPoint(const TThickPoint &point, double pixelSize2); + void flushTrackPoint(); + bool doFrameRangeStrokes(TFrameId firstFrameId, TStroke *firstStroke, + TFrameId lastFrameId, TStroke *lastStroke, + bool drawFirstStroke = true); + void checkGuideSnapping(bool beforeMousePress, bool invertCheck); + void checkStrokeSnapping(bool beforeMousePress, bool invertCheck); + +protected: + TPropertyGroup m_prop[2]; + + TDoublePairProperty m_thickness; + TDoubleProperty m_accuracy; + TDoubleProperty m_smooth; + TEnumProperty m_preset; + TBoolProperty m_breakAngles; + TBoolProperty m_pressure; + TBoolProperty m_snap; + TEnumProperty m_frameRange; + TEnumProperty m_snapSensitivity; + TEnumProperty m_capStyle; + TEnumProperty m_joinStyle; + TIntProperty m_miterJoinLimit; + + StrokeGenerator m_track; + StrokeGenerator m_rangeTrack; + RasterStrokeGenerator *m_rasterTrack; + TStroke *m_firstStroke; + TTileSetCM32 *m_tileSet; + TTileSaverCM32 *m_tileSaver; + TFrameId m_firstFrameId, m_veryFirstFrameId; + TPixel32 m_currentColor; + int m_styleId; + double m_minThick, m_maxThick; + + // for snapping and framerange + int m_strokeIndex1, m_strokeIndex2, m_col, m_firstFrame, m_veryFirstFrame, + m_veryFirstCol, m_targetType; + double m_w1, m_w2, m_pixelSize, m_currThickness, m_minDistance2; + bool m_foundFirstSnap = false, m_foundLastSnap = false, m_dragDraw = true, + m_altPressed = false, m_snapSelf = false; + TRectD m_modifiedRegion; + TPointD m_dpiScale, + m_mousePos, //!< Current mouse position, in world coordinates. + m_brushPos, //!< World position the brush will be painted at. + m_firstSnapPoint, m_lastSnapPoint; + + BluredBrush *m_bluredBrush; + QRadialGradient m_brushPad; + + TRasterCM32P m_backupRas; + TRaster32P m_workRas; + + std::vector m_points; + TRect m_strokeRect, m_lastRect; + + SmoothStroke m_smoothStroke; + + VectorBrushPresetManager + m_presetsManager; //!< Manager for presets of this tool instance + + bool m_active, m_enabled, + m_isPrompting, //!< Whether the tool is prompting for spline + //! substitution. + m_firstTime, m_isPath, m_presetsLoaded, m_firstFrameRange; + + /*--- + ��ƒ���FrameId���N���b�N���ɕۑ����A�}�E�X�����[�X���iUndo�̓o�^���j�ɕʂ̃t���[���� + �ړ����Ă����Ƃ��̕s����C������B---*/ + TFrameId m_workingFrameId; +}; + +#endif // TOONZVECTORBRUSHTOOL_H diff --git a/toonz/sources/tnztools/trackertool.cpp b/toonz/sources/tnztools/trackertool.cpp index 99a0a0d..6a6f449 100644 --- a/toonz/sources/tnztools/trackertool.cpp +++ b/toonz/sources/tnztools/trackertool.cpp @@ -324,11 +324,8 @@ void TrackerTool::draw() { glPushMatrix(); glTranslated(hook->getPos(fid).x, hook->getPos(fid).y, 0); glScaled(pixelSize, pixelSize, 1); - int objectId = hook->getTrackerObjectId(); - char *objectChar = (char *)malloc(2); - objectChar[0] = (char)(objectId + 65); - objectChar[1] = '\0'; - std::string text(objectChar); + int objectId = hook->getTrackerObjectId(); + std::string text({static_cast('A' + objectId)}); tglDrawText(TPointD(-15, 10), text); glPopMatrix(); } diff --git a/toonz/sources/tnztools/typetool.cpp b/toonz/sources/tnztools/typetool.cpp index 3739c52..8c985c8 100644 --- a/toonz/sources/tnztools/typetool.cpp +++ b/toonz/sources/tnztools/typetool.cpp @@ -295,7 +295,7 @@ class TypeTool final : public TTool { TEnumProperty m_typeFaceMenu; TBoolProperty m_vertical; TEnumProperty m_size; - TPropertyGroup m_prop; + TPropertyGroup m_prop[2]; // valori correnti di alcune Properties, // duplicati per permettere controlli sulla validita' o per ottimizzazione @@ -389,7 +389,9 @@ public: bool onPropertyChanged(std::string propertyName) override; - TPropertyGroup *getProperties(int targetType) override { return &m_prop; } + TPropertyGroup *getProperties(int targetType) override { + return &m_prop[targetType]; + } int getColorClass() const { return 1; } @@ -421,15 +423,15 @@ TypeTool::TypeTool() , m_size("Size:") // W_ToolOptions_Size , m_undo(0) { bind(TTool::CommonLevels | TTool::EmptyTarget); - m_prop.bind(m_fontFamilyMenu); + m_prop[0].bind(m_fontFamilyMenu); // Su mac non e' visibile il menu dello style perche' e' stato inserito nel // nome // della font. //#ifndef MACOSX - m_prop.bind(m_typeFaceMenu); + m_prop[1].bind(m_typeFaceMenu); //#endif - m_prop.bind(m_size); - m_prop.bind(m_vertical); + m_prop[1].bind(m_size); + m_prop[1].bind(m_vertical); m_vertical.setId("Orientation"); m_fontFamilyMenu.setId("TypeFont"); m_typeFaceMenu.setId("TypeStyle"); @@ -537,6 +539,9 @@ void TypeTool::initTypeFaces() { it != typefaces.end(); ++it) m_typeFaceMenu.addValue(*it); if (m_typeFaceMenu.isValue(oldTypeface)) m_typeFaceMenu.setValue(oldTypeface); + + TTool::getApplication()->getCurrentTool()->notifyToolComboBoxListChanged( + m_typeFaceMenu.getName()); } //--------------------------------------------------------- @@ -1611,6 +1616,7 @@ bool TypeTool::keyDown(QKeyEvent *event) { break; default: + if (unicodeChar.empty()) return false; replaceText(unicodeChar, m_cursorIndex, m_cursorIndex); m_cursorIndex++; m_preeditRange = std::make_pair(m_cursorIndex, m_cursorIndex); diff --git a/toonz/sources/tnztools/vectorerasertool.cpp b/toonz/sources/tnztools/vectorerasertool.cpp index ee04710..9ea979c 100644 --- a/toonz/sources/tnztools/vectorerasertool.cpp +++ b/toonz/sources/tnztools/vectorerasertool.cpp @@ -744,8 +744,8 @@ intersect( *oldStroke, pos, m_pointSize, intersections ); //----------------------------------------------------------------------------- void EraserTool::erase(TVectorImageP vi, TRectD &rect) { - if (rect.x0 > rect.x1) tswap(rect.x1, rect.x0); - if (rect.y0 > rect.y1) tswap(rect.y1, rect.y0); + if (rect.x0 > rect.x1) std::swap(rect.x1, rect.x0); + if (rect.y0 > rect.y1) std::swap(rect.y1, rect.y0); int i = 0; int index = TTool::getApplication()->getCurrentLevelStyleIndex(); std::vector eraseStrokes; @@ -834,6 +834,7 @@ void EraserTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { invalidate(); return; } else if (m_eraseType.getValue() == NORMAL_ERASE) { + if (!m_undo) leftButtonDown(pos, e); if (TVectorImageP vi = image) erase(vi, pos); } else if (m_eraseType.getValue() == FREEHAND_ERASE) { freehandDrag(pos); @@ -849,9 +850,9 @@ void EraserTool::multiEraseRect(TFrameId firstFrameId, TFrameId lastFrameId, int r1 = lastFrameId.getNumber(); if (r0 > r1) { - tswap(r0, r1); - tswap(firstFrameId, lastFrameId); - tswap(firstRect, lastRect); + std::swap(r0, r1); + std::swap(firstFrameId, lastFrameId); + std::swap(firstRect, lastRect); } if ((r1 - r0) < 1) return; @@ -937,13 +938,14 @@ void EraserTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) { TTool::Application *application = TTool::getApplication(); if (!vi || !application) return; - if (m_eraseType.getValue() == NORMAL_ERASE) + if (m_eraseType.getValue() == NORMAL_ERASE) { + if (!m_undo) leftButtonDown(pos, e); stopErase(vi); - else if (m_eraseType.getValue() == RECT_ERASE) { + } else if (m_eraseType.getValue() == RECT_ERASE) { if (m_selectingRect.x0 > m_selectingRect.x1) - tswap(m_selectingRect.x1, m_selectingRect.x0); + std::swap(m_selectingRect.x1, m_selectingRect.x0); if (m_selectingRect.y0 > m_selectingRect.y1) - tswap(m_selectingRect.y1, m_selectingRect.y0); + std::swap(m_selectingRect.y1, m_selectingRect.y0); if (m_multi.getValue()) { if (m_firstFrameSelected) { @@ -1278,7 +1280,7 @@ void EraserTool::doMultiErase(TFrameId &firstFrameId, TFrameId &lastFrameId, bool backward = false; if (firstFrameId > lastFrameId) { - tswap(firstFrameId, lastFrameId); + std::swap(firstFrameId, lastFrameId); backward = true; } assert(firstFrameId <= lastFrameId); diff --git a/toonz/sources/tnztools/vectorselectiontool.cpp b/toonz/sources/tnztools/vectorselectiontool.cpp index bc413cf..c0c206c 100644 --- a/toonz/sources/tnztools/vectorselectiontool.cpp +++ b/toonz/sources/tnztools/vectorselectiontool.cpp @@ -568,9 +568,9 @@ DragSelectionTool::VectorDeformTool::~VectorDeformTool() { void DragSelectionTool::VectorDeformTool::applyTransform(FourPoints bbox) { SelectionTool *tool = getTool(); - tcg::unique_ptr localVfdScopedBlock; - if (!m_vfdScopedBlock.get()) { - tcg::unique_ptr &vfdScopedBlock = + std::unique_ptr localVfdScopedBlock; + if (!m_vfdScopedBlock) { + std::unique_ptr &vfdScopedBlock = m_isDragging ? m_vfdScopedBlock : localVfdScopedBlock; vfdScopedBlock.reset(new VFDScopedBlock(tool)); @@ -584,7 +584,7 @@ void DragSelectionTool::VectorDeformTool::applyTransform(FourPoints bbox) { freeDeformer->setPreserveThickness(tool->isConstantThickness()); freeDeformer->setFlip(isFlip()); - if (!TTool::getApplication()->getCurrentObject()->isSpline() && m_undo.get()) + if (!TTool::getApplication()->getCurrentObject()->isSpline() && m_undo) m_undo->setFlip(isFlip()); freeDeformer->deformImage(); @@ -608,7 +608,7 @@ void DragSelectionTool::VectorDeformTool::addTransformUndo() { ->getXsheet() ->getStageObject(getTool()->getObjectId()) ->getSpline())); - else if (m_undo.get()) { + else if (m_undo) { m_undo->registerStrokes(); TUndoManager::manager()->add(m_undo.release()); } @@ -652,7 +652,7 @@ void DragSelectionTool::VectorDeformTool::transformWholeLevel() { TVectorImageP vi = level->getFrame(fid, true); if (!vi) continue; - tcg::unique_ptr undo( + std::unique_ptr undo( new UndoChangeStrokes(level, fid, tool, tool->levelSelection())); std::set strokesIndices; @@ -704,7 +704,7 @@ bool DragSelectionTool::VectorDeformTool::isFlip() { void DragSelectionTool::VectorDeformTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e) { - tcg::unique_ptr vfdScopedBlock(m_vfdScopedBlock.release()); + std::unique_ptr vfdScopedBlock(std::move(m_vfdScopedBlock)); SelectionTool *tool = getTool(); VectorFreeDeformer *deformer = @@ -1046,7 +1046,7 @@ void DragSelectionTool::VectorChangeThicknessTool::addUndo() { } // Transform fid's selection - tcg::unique_ptr undo( + std::unique_ptr undo( new UndoChangeStrokes(level, fid, vtool, vtool->levelSelection())); setStrokesThickness(*vi); diff --git a/toonz/sources/tnztools/vectorselectiontool.h b/toonz/sources/tnztools/vectorselectiontool.h index 8a40723..94109a1 100644 --- a/toonz/sources/tnztools/vectorselectiontool.h +++ b/toonz/sources/tnztools/vectorselectiontool.h @@ -16,9 +16,6 @@ // Qt includes #include -// tcg includes -#include "tcg/tcg_unique_ptr.h" - //============================================================ // Forward declarations @@ -160,7 +157,7 @@ public: bool isFlip(); protected: - tcg::unique_ptr m_undo; + std::unique_ptr m_undo; protected: void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override {} @@ -171,7 +168,7 @@ protected: private: struct VFDScopedBlock; - tcg::unique_ptr m_vfdScopedBlock; + std::unique_ptr m_vfdScopedBlock; }; //============================================================================= @@ -179,7 +176,7 @@ private: //----------------------------------------------------------------------------- class VectorRotationTool final : public VectorDeformTool { - tcg::unique_ptr m_rotation; + std::unique_ptr m_rotation; public: VectorRotationTool(VectorSelectionTool *tool); @@ -194,7 +191,7 @@ public: //----------------------------------------------------------------------------- class VectorFreeDeformTool final : public VectorDeformTool { - tcg::unique_ptr m_freeDeform; + std::unique_ptr m_freeDeform; public: VectorFreeDeformTool(VectorSelectionTool *tool); @@ -207,7 +204,7 @@ public: //----------------------------------------------------------------------------- class VectorMoveSelectionTool final : public VectorDeformTool { - tcg::unique_ptr m_moveSelection; + std::unique_ptr m_moveSelection; public: VectorMoveSelectionTool(VectorSelectionTool *tool); @@ -222,7 +219,7 @@ public: //----------------------------------------------------------------------------- class VectorScaleTool final : public VectorDeformTool { - tcg::unique_ptr m_scale; + std::unique_ptr m_scale; public: VectorScaleTool(VectorSelectionTool *tool, int type); @@ -243,7 +240,7 @@ class VectorChangeThicknessTool final : public DragTool { std::map> m_strokesThickness; double m_thicknessChange; - tcg::unique_ptr m_undo; + std::unique_ptr m_undo; public: VectorChangeThicknessTool(VectorSelectionTool *tool); diff --git a/toonz/sources/tnztools/vectortapetool.cpp b/toonz/sources/tnztools/vectortapetool.cpp index 3fba465..592f022 100644 --- a/toonz/sources/tnztools/vectortapetool.cpp +++ b/toonz/sources/tnztools/vectortapetool.cpp @@ -668,8 +668,8 @@ public: ? ((m_w2 == 0.0 || m_w2 == 1.0) ? p2p : p2l) : ((m_w2 == 0.0 || m_w2 == 1.0) ? l2p : l2l); if (type == l2p) { - tswap(m_strokeIndex1, m_strokeIndex2); - tswap(m_w1, m_w2); + std::swap(m_strokeIndex1, m_strokeIndex2); + std::swap(m_w1, m_w2); type = p2l; } } diff --git a/toonz/sources/toonz/CMakeLists.txt b/toonz/sources/toonz/CMakeLists.txt index e914f41..e7fcba1 100644 --- a/toonz/sources/toonz/CMakeLists.txt +++ b/toonz/sources/toonz/CMakeLists.txt @@ -107,7 +107,6 @@ set(MOC_HEADERS sceneviewerevents.h scriptconsolepanel.h selectionutils.h - shifttracetool.h shortcutpopup.h soundtrackexport.h startuppopup.h @@ -123,6 +122,7 @@ set(MOC_HEADERS svnupdatedialog.h svnpurgedialog.h tapp.h + kis_tablet_support_win8.h tasksviewer.h testpanel.h tfarmstuff.h @@ -158,6 +158,9 @@ set(MOC_HEADERS reframepopup.h autoinputcellnumberpopup.h colormodelbehaviorpopup.h + boardsettingspopup.h + separatecolorsswatch.h + separatecolorspopup.h # Tracker file dummyprocessor.h metnum.h @@ -254,11 +257,11 @@ set(SOURCES sceneviewercontextmenu.cpp scenesettingspopup.cpp scriptconsolepanel.cpp - shifttracetool.cpp shortcutpopup.cpp soundtrackexport.cpp startuppopup.cpp subcameramanager.cpp + kis_tablet_support_win8.cpp timestretchpopup.cpp trackerpopup.cpp vectorizerpopup.cpp @@ -331,6 +334,9 @@ set(SOURCES reframepopup.cpp autoinputcellnumberpopup.cpp colormodelbehaviorpopup.cpp + boardsettingspopup.cpp + separatecolorsswatch.cpp + separatecolorspopup.cpp # Tracker file dummyprocessor.cpp metnum.cpp @@ -359,11 +365,11 @@ endif() qt5_wrap_cpp(SOURCES ${MOC_HEADERS}) if(BUILD_ENV_MSVC) - add_executable(OpenToonz_${VERSION} WIN32 ${HEADERS} ${SOURCES} ${OBJCSOURCES} ${RESOURCES} ${RC_FILE}) + add_executable(OpenToonz WIN32 ${HEADERS} ${SOURCES} ${OBJCSOURCES} ${RESOURCES} ${RC_FILE}) else() set(MACOSX_BUNDLE_ICON_FILE "OpenToonz.icns") set_source_files_properties(OpenToonz.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") - add_executable(OpenToonz_${VERSION} MACOSX_BUNDLE OpenToonz.icns ${HEADERS} ${SOURCES} ${OBJCSOURCES} ${RESOURCES}) + add_executable(OpenToonz MACOSX_BUNDLE OpenToonz.icns ${HEADERS} ${SOURCES} ${OBJCSOURCES} ${RESOURCES}) #add_definitions( # -DTNZBASE_EXPORTS # -DTPARAM_EXPORTS @@ -408,7 +414,7 @@ if(BUILD_TARGET_WIN) endif() if(BUILD_ENV_MSVC) - target_link_libraries(OpenToonz_${VERSION} + target_link_libraries(OpenToonz Qt5::WinMain Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml Qt5::Script Qt5::Widgets Qt5::PrintSupport Qt5::Multimedia ${GL_LIB} ${GLUT_LIB} strmiids @@ -422,9 +428,9 @@ elseif(BUILD_ENV_APPLE) # 変なところにライブラリ生成するカスども set(EXTRA_LIBS ${EXTRA_LIBS} "$" "$") - add_dependencies(OpenToonz_${VERSION} tnzcore tnzbase toonzlib colorfx tnzext image sound toonzqt tnztools tnzstdfx tfarm) + add_dependencies(OpenToonz tnzcore tnzbase toonzlib colorfx tnzext image sound toonzqt tnztools tnzstdfx tfarm) - target_link_libraries(OpenToonz_${VERSION} + target_link_libraries(OpenToonz Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml Qt5::Script Qt5::Widgets Qt5::PrintSupport Qt5::Multimedia Qt5::MultimediaWidgets ${GL_LIB} ${GLUT_LIB} @@ -444,7 +450,7 @@ elseif(BUILD_ENV_UNIXLIKE) endif() target_link_libraries( - OpenToonz_${VERSION} Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml + OpenToonz Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml Qt5::Script Qt5::Widgets Qt5::PrintSupport Qt5::Multimedia ${GL_LIB} ${GLUT_LIB} ${GLU_LIB} ${EXTRA_LIBS} @@ -454,7 +460,7 @@ endif() if(BUILD_ENV_APPLE) # CMAKE_RUNTIME_OUTPUT_DIRECTORY should be equivalent to usage on windows despite empty # OSX だと CMAKE_RUNTIME_OUTPUT_DIRECTORY が空だが Windows 版と同じ使い方ができるようにしておく - get_target_property(bin OpenToonz_${VERSION} LOCATION) + get_target_property(bin OpenToonz LOCATION) get_filename_component(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${bin} DIRECTORY) # show CMAKE_RUNTIME_OUTPUT_DIRECTORY message("CMAKE_RUNTIME_OUTPUT_DIRECTORY:" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) @@ -462,44 +468,44 @@ endif() # copy utilty executables onto the directory after build if(LZODRIVER_FOUND) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS lzocompress) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS lzodecompress) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS lzocompress) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS lzodecompress) endif() if(BUILD_ENV_APPLE) - get_target_property(loc OpenToonz_${VERSION} MACOSX_BUNDLE_NAME) + get_target_property(loc OpenToonz MACOSX_BUNDLE_NAME) message(" ==> App Bundle: " ${loc}) message(" ==> Mach-o: " ${bin}) foreach(lib ${EXTRA_LIBS}) - message(" copy:" ${lib} "==>" ${CMAKE_CURRENT_BINARY_DIR}/OpenToonz_${VERSION}.app/Contents/MacOS/) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND cp ${lib} ${CMAKE_CURRENT_BINARY_DIR}/OpenToonz_${VERSION}.app/Contents/MacOS/) + message(" copy:" ${lib} "==>" ${CMAKE_CURRENT_BINARY_DIR}/OpenToonz.app/Contents/MacOS/) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND cp ${lib} ${CMAKE_CURRENT_BINARY_DIR}/OpenToonz.app/Contents/MacOS/) endforeach() - add_custom_command(TARGET OpenToonz_${VERSION} + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath @executable_path/. ${bin} ) - add_custom_command(TARGET OpenToonz_${VERSION} + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath ${CMAKE_INSTALL_RPATH} ${bin} ) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/OpenToonz_${VERSION}.app/Contents/Resources) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/OpenToonz.app/Contents/Resources) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/OpenToonz_${VERSION}.app/Contents/Resources) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/qss) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../install/SystemVar.ini ${CMAKE_CURRENT_BINARY_DIR}/OpenToonz_${VERSION}.app/Contents/Resources) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/OpenToonz.app/Contents/Resources) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/qss) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../install/SystemVar.ini ${CMAKE_CURRENT_BINARY_DIR}/OpenToonz.app/Contents/Resources) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS tcomposer) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS tcleanup) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS tconverter) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS tfarmcontroller) - add_custom_command(TARGET OpenToonz_${VERSION} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS tfarmserver) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS tcomposer) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS tcleanup) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS tconverter) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS tfarmcontroller) + add_custom_command(TARGET OpenToonz POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} DEPENDS tfarmserver) elseif(BUILD_ENV_UNIXLIKE AND BUILD_TARGET_WIN) # Setup files on Windows platform while cross compilation. install( TARGETS - OpenToonz_${VERSION} + OpenToonz DESTINATION bin ) @@ -553,7 +559,7 @@ elseif(BUILD_ENV_UNIXLIKE AND NOT BUILD_TARGET_WIN) # - /usr install( TARGETS - OpenToonz_${VERSION} + OpenToonz DESTINATION bin ) @@ -597,7 +603,7 @@ fi export LD_LIBRARY_PATH=\${OPENTOONZ_BASE}/lib/opentoonz:\${LD_LIBRARY_PATH} -exec \$OPENTOONZ_BASE/bin/OpenToonz_${VERSION} \"\$@\" +exec \$OPENTOONZ_BASE/bin/OpenToonz \"\$@\" ") # only needed for executing without installing execute_process(COMMAND chmod +x ${CMAKE_BINARY_DIR}/bin/opentoonz) diff --git a/toonz/sources/toonz/Resources/down.svg b/toonz/sources/toonz/Resources/down.svg new file mode 100644 index 0000000..4e43af1 --- /dev/null +++ b/toonz/sources/toonz/Resources/down.svg @@ -0,0 +1,49 @@ + +image/svg+xml \ No newline at end of file diff --git a/toonz/sources/toonz/Resources/shift_and_trace.svg b/toonz/sources/toonz/Resources/shift_and_trace.svg new file mode 100644 index 0000000..b97685d --- /dev/null +++ b/toonz/sources/toonz/Resources/shift_and_trace.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/toonz/sources/toonz/Resources/shift_and_trace_edit.svg b/toonz/sources/toonz/Resources/shift_and_trace_edit.svg new file mode 100644 index 0000000..cb78a22 --- /dev/null +++ b/toonz/sources/toonz/Resources/shift_and_trace_edit.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/toonz/sources/toonz/Resources/shift_and_trace_reset.svg b/toonz/sources/toonz/Resources/shift_and_trace_reset.svg new file mode 100644 index 0000000..6e85189 --- /dev/null +++ b/toonz/sources/toonz/Resources/shift_and_trace_reset.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/toonz/sources/toonz/Resources/up.svg b/toonz/sources/toonz/Resources/up.svg new file mode 100644 index 0000000..5621f63 --- /dev/null +++ b/toonz/sources/toonz/Resources/up.svg @@ -0,0 +1,49 @@ + +image/svg+xml \ No newline at end of file diff --git a/toonz/sources/toonz/antialiaspopup.cpp b/toonz/sources/toonz/antialiaspopup.cpp index 58f1c48..74a95be 100644 --- a/toonz/sources/toonz/antialiaspopup.cpp +++ b/toonz/sources/toonz/antialiaspopup.cpp @@ -289,7 +289,11 @@ public: , m_softness(softness) , m_rasSize(ras->getLx() * ras->getLy() * ras->getPixelSize()) { m_rasId = QString("AntialiasUndo_") + QString::number(uintptr_t(this)); - TImageCache::instance()->add(m_rasId, TRasterImageP(ras)); + if ((TRasterCM32P)ras) + TImageCache::instance()->add(m_rasId, + TToonzImageP(ras, ras->getBounds())); + else + TImageCache::instance()->add(m_rasId, TRasterImageP(ras)); } ~TRasterAntialiasUndo() { TImageCache::instance()->remove(m_rasId); } @@ -311,7 +315,6 @@ public: ((TToonzImageP)TImageCache::instance()->get(m_rasId, true)) ->getRaster() ->clone()); - TXshSimpleLevel *simpleLevel = cell.getSimpleLevel(); assert(simpleLevel); simpleLevel->touchFrame(cell.getFrameId()); @@ -324,10 +327,12 @@ public: } void redo() const override { - TXsheet *xsheet = TApp::instance()->getCurrentXsheet()->getXsheet(); - TXshCell cell = xsheet->getCell(m_r, m_c); - TImageP image = (TRasterImageP)cell.getImage(true); - if (!image) return; + TXsheet *xsheet = TApp::instance()->getCurrentXsheet()->getXsheet(); + TXshCell cell = xsheet->getCell(m_r, m_c); + TImageP image = cell.getImage(true); + TRasterImageP rimg = (TRasterImageP)image; + TToonzImageP timg = (TToonzImageP)image; + if (!rimg && !timg) return; TRasterP ras = image->raster(); if (!ras) return; @@ -343,6 +348,8 @@ public: } int getSize() const override { return sizeof(*this) + m_rasSize; } + + QString getHistoryString() override { return QObject::tr("Apply Antialias"); } }; //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/audiorecordingpopup.cpp b/toonz/sources/toonz/audiorecordingpopup.cpp index 9a38077..a71e78c 100644 --- a/toonz/sources/toonz/audiorecordingpopup.cpp +++ b/toonz/sources/toonz/audiorecordingpopup.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include diff --git a/toonz/sources/toonz/boardsettingspopup.cpp b/toonz/sources/toonz/boardsettingspopup.cpp new file mode 100644 index 0000000..78aecf9 --- /dev/null +++ b/toonz/sources/toonz/boardsettingspopup.cpp @@ -0,0 +1,1089 @@ +#include "boardsettingspopup.h" + +// Tnz6 includes +#include "tapp.h" +#include "filebrowser.h" + +// TnzQt includes +#include "toonzqt/filefield.h" +#include "toonzqt/colorfield.h" +#include "toonzqt/intfield.h" + +// TnzLib includes +#include "toutputproperties.h" +#include "toonz/tscenehandle.h" +#include "toonz/toonzscene.h" +#include "toonz/sceneproperties.h" +#include "toonz/tcamera.h" +#include "toonz/boardsettings.h" +#include "toonz/toonzfolders.h" + +// TnzBase includes +#include "trasterfx.h" + +// TnzCore includes +#include "tsystem.h" +#include "tlevel_io.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +BoardItem* BoardSettingsPopup::currentBoardItem = nullptr; + +namespace { +QMap stringByItemType; + +BoardItem* currentBoardItem() { return BoardSettingsPopup::currentBoardItem; } +void setCurrentBoardItem(BoardItem* item) { + BoardSettingsPopup::currentBoardItem = item; +} + +void editListWidgetItem(QListWidgetItem* listItem, BoardItem* item) { + QString itemText = item->getName() + "\n(" + + stringByItemType.value(item->getType(), "Unknown type") + + ")"; + listItem->setText(itemText); + + if (item->getType() == BoardItem::Image) { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + TFilePath decodedImgPath = scene->decodeFilePath(item->getImgPath()); + QPixmap iconPm = QPixmap::fromImage( + QImage(decodedImgPath.getQString()).scaled(QSize(20, 20))); + listItem->setIcon(QIcon(iconPm)); + } else { + QPixmap iconPm(20, 20); + iconPm.fill(item->getColor()); + listItem->setIcon(QIcon(iconPm)); + } +} +} + +//============================================================================= + +BoardView::BoardView(QWidget* parent) : QWidget(parent) { + setMouseTracking(true); +} + +void BoardView::paintEvent(QPaintEvent* event) { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + QPainter p(this); + + p.fillRect(rect(), Qt::black); + + // Duration must be more than 0 to save the clapperboard. + // Scene file can maintain compatibility with older versions if you set the + // duration to 0. + if (boardSettings->getDuration() == 0) { + p.setPen(Qt::white); + QFont font = p.font(); + font.setPixelSize(30); + p.setFont(font); + p.drawText( + rect().adjusted(5, 5, -5, -5), Qt::AlignCenter | Qt::TextWordWrap, + tr("Please set the duration more than 0 frame first, or the " + "clapperboard settings will not be saved in the scene at all!")); + + p.setPen(QPen(Qt::red, 2)); + p.drawLine(5, 5, 150, 5); + p.drawLine(5, 10, 150, 10); + + return; + } + + if (!m_valid) { + int shrinkX = outProp->getRenderSettings().m_shrinkX, + shrinkY = outProp->getRenderSettings().m_shrinkY; + TDimension frameSize = scene->getCurrentCamera()->getRes(); + TDimension cameraRes(frameSize.lx / shrinkX, frameSize.ly / shrinkY); + + m_boardImg = boardSettings->getBoardImage(cameraRes, shrinkX, scene); + m_valid = true; + } + + p.drawImage(m_boardImgRect, m_boardImg); + + p.translate(m_boardImgRect.topLeft()); + + p.setBrush(Qt::NoBrush); + for (int i = 0; i < boardSettings->getItemCount(); i++) { + BoardItem* item = &(boardSettings->getItem(i)); + if (item == currentBoardItem()) { + p.setPen(QPen(QColor(255, 100, 0), 2)); + } else { + p.setPen(QPen(QColor(64, 64, 255), 1, Qt::DashLine)); + } + p.drawRect(item->getItemRect(m_boardImgRect.size().toSize())); + } +} + +void BoardView::resizeEvent(QResizeEvent* event) { + QSize boardRes; + if (m_valid) { + boardRes = m_boardImg.size(); + } else { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + int shrinkX = outProp->getRenderSettings().m_shrinkX, + shrinkY = outProp->getRenderSettings().m_shrinkY; + TDimension frameSize = scene->getCurrentCamera()->getRes(); + boardRes = QSize(frameSize.lx / shrinkX, frameSize.ly / shrinkY); + } + + float ratio = std::min((float)width() / (float)boardRes.width(), + (float)height() / (float)boardRes.height()); + QSizeF imgSize = QSizeF(boardRes) * ratio; + QPointF imgTopLeft(((float)width() - imgSize.width()) * 0.5, + ((float)height() - imgSize.height()) * 0.5); + + m_boardImgRect = QRectF(imgTopLeft, imgSize); +} + +void BoardView::mouseMoveEvent(QMouseEvent* event) { + // mouse move - change drag item + if (!(event->buttons() & Qt::LeftButton)) { + if (!currentBoardItem()) { + m_dragItem = None; + setCursor(Qt::ArrowCursor); + return; + } + + QPointF posOnImg = QPointF(event->pos()) - m_boardImgRect.topLeft(); + + QRectF itemRect = + currentBoardItem()->getItemRect(m_boardImgRect.size().toSize()); + + qreal distance = 10.0; + + if ((itemRect.topLeft() - posOnImg).manhattanLength() < distance) { + m_dragItem = TopLeftCorner; + setCursor(Qt::SizeFDiagCursor); + } else if ((itemRect.topRight() - posOnImg).manhattanLength() < distance) { + m_dragItem = TopRightCorner; + setCursor(Qt::SizeBDiagCursor); + } else if ((itemRect.bottomRight() - posOnImg).manhattanLength() < + distance) { + m_dragItem = BottomRightCorner; + setCursor(Qt::SizeFDiagCursor); + } else if ((itemRect.bottomLeft() - posOnImg).manhattanLength() < + distance) { + m_dragItem = BottomLeftCorner; + setCursor(Qt::SizeBDiagCursor); + } else if (std::abs(itemRect.top() - posOnImg.y()) < distance && + itemRect.left() < posOnImg.x() && + itemRect.right() > posOnImg.x()) { + m_dragItem = TopEdge; + setCursor(Qt::SizeVerCursor); + } else if (std::abs(itemRect.right() - posOnImg.x()) < distance && + itemRect.top() < posOnImg.y() && + itemRect.bottom() > posOnImg.y()) { + m_dragItem = RightEdge; + setCursor(Qt::SizeHorCursor); + } else if (std::abs(itemRect.bottom() - posOnImg.y()) < distance && + itemRect.left() < posOnImg.x() && + itemRect.right() > posOnImg.x()) { + m_dragItem = BottomEdge; + setCursor(Qt::SizeVerCursor); + } else if (std::abs(itemRect.left() - posOnImg.x()) < distance && + itemRect.top() < posOnImg.y() && + itemRect.bottom() > posOnImg.y()) { + m_dragItem = LeftEdge; + setCursor(Qt::SizeHorCursor); + } else if (itemRect.contains(posOnImg)) { + m_dragItem = Translate; + setCursor(Qt::SizeAllCursor); + } else { + m_dragItem = None; + setCursor(Qt::ArrowCursor); + } + + return; + } + + // left mouse drag + if (m_dragItem == None) return; + + if (m_dragStartItemRect.isNull()) return; + + QPointF posOnImg = QPointF(event->pos()) - m_boardImgRect.topLeft(); + QPointF ratioPos = QPointF(posOnImg.x() / m_boardImgRect.width(), + posOnImg.y() / m_boardImgRect.height()); + + // with alt : center resize + bool altPressed = event->modifiers() & Qt::AltModifier; + // with shift : align to discrete position + bool shiftPressed = event->modifiers() & Qt::ShiftModifier; + + auto adjVal = [&](double p) { + double step = 0.05; + if (!shiftPressed) return p; + return std::round(p / step) * step; + }; + auto adjPos = [&](QPointF p) { + if (!shiftPressed) return p; + return QPointF(adjVal(p.x()), adjVal(p.y())); + }; + + QRectF newRect = m_dragStartItemRect; + QPointF d = ratioPos - m_dragStartPos; + switch (m_dragItem) { + case Translate: + newRect.translate(ratioPos - m_dragStartPos); + if (shiftPressed) { + newRect.setTopLeft(adjPos(newRect.topLeft())); + newRect.setBottomRight(adjPos(newRect.bottomRight())); + } + break; + + case TopLeftCorner: + newRect.setTopLeft(adjPos(newRect.topLeft() + d)); + if (altPressed) newRect.setBottomRight(adjPos(newRect.bottomRight() - d)); + break; + + case TopRightCorner: + newRect.setTopRight(adjPos(newRect.topRight() + d)); + if (altPressed) newRect.setBottomLeft(adjPos(newRect.bottomLeft() - d)); + break; + + case BottomRightCorner: + newRect.setBottomRight(adjPos(newRect.bottomRight() + d)); + if (altPressed) newRect.setTopLeft(adjPos(newRect.topLeft() - d)); + break; + + case BottomLeftCorner: + newRect.setBottomLeft(adjPos(newRect.bottomLeft() + d)); + if (altPressed) newRect.setTopRight(adjPos(newRect.topRight() - d)); + break; + + case TopEdge: + newRect.setTop(adjVal(newRect.top() + d.y())); + if (altPressed) newRect.setBottom(adjVal(newRect.bottom() - d.y())); + break; + + case RightEdge: + newRect.setRight(adjVal(newRect.right() + d.x())); + if (altPressed) newRect.setLeft(adjVal(newRect.left() - d.x())); + break; + + case BottomEdge: + newRect.setBottom(adjVal(newRect.bottom() + d.y())); + if (altPressed) newRect.setTop(adjVal(newRect.top() - d.y())); + break; + + case LeftEdge: + newRect.setLeft(adjVal(newRect.left() + d.x())); + if (altPressed) newRect.setRight(adjVal(newRect.right() - d.x())); + break; + default: + break; + } + + currentBoardItem()->setRatioRect(newRect.normalized()); + invalidate(); + update(); +} + +void BoardView::mousePressEvent(QMouseEvent* event) { + // only the left button counts + if (event->button() != Qt::LeftButton) return; + // store the current item rect and mouse pos, relative to the image size + m_dragStartItemRect = currentBoardItem()->getRatioRect(); + QPointF posOnImg = QPointF(event->pos()) - m_boardImgRect.topLeft(); + m_dragStartPos = QPointF(posOnImg.x() / m_boardImgRect.width(), + posOnImg.y() / m_boardImgRect.height()); +} + +void BoardView::mouseReleaseEvent(QMouseEvent* event) { + m_dragStartItemRect = QRectF(); + m_dragStartPos = QPointF(); +} + +//============================================================================= + +ItemInfoView::ItemInfoView(QWidget* parent) : QStackedWidget(parent) { + m_nameEdit = new QLineEdit(this); + m_maxFontSizeEdit = new DVGui::IntLineEdit(this, 1, 1); + m_typeCombo = new QComboBox(this); + m_textEdit = new QTextEdit(this); + m_imgPathField = new DVGui::FileField(this); + m_fontCombo = new QFontComboBox(this); + m_boldButton = + new QPushButton(QIcon(":Resources/bold_on.png"), tr("Bold"), this); + m_italicButton = + new QPushButton(QIcon(":Resources/italic_on.png"), tr("Italic"), this); + m_fontColorField = + new DVGui::ColorField(this, true, TPixel32(0, 0, 0, 255), 25, false, 54); + m_imgARModeCombo = new QComboBox(this); + + m_fontPropBox = new QWidget(this); + m_imgPropBox = new QWidget(this); + + for (int i = 0; i < BoardItem::TypeCount; i++) { + m_typeCombo->addItem(stringByItemType[(BoardItem::Type)i]); + } + + m_textEdit->setAcceptRichText(false); + m_textEdit->setStyleSheet( + "background:white;\ncolor:black;\nborder:1 solid black;"); + + m_boldButton->setIconSize(QSize(30, 30)); + m_boldButton->setFixedHeight(25); + m_boldButton->setCheckable(true); + m_italicButton->setIconSize(QSize(30, 30)); + m_italicButton->setFixedHeight(25); + m_italicButton->setCheckable(true); + + QStringList filters; + for (QByteArray& format : QImageReader::supportedImageFormats()) + filters += format; + m_imgPathField->setFilters(filters); + m_imgPathField->setFileMode(QFileDialog::ExistingFile); + + m_imgARModeCombo->addItem(tr("Ignore"), Qt::IgnoreAspectRatio); + m_imgARModeCombo->addItem(tr("Keep"), Qt::KeepAspectRatio); + + //----- layout + + QGridLayout* mainLay = new QGridLayout(); + mainLay->setMargin(5); + mainLay->setHorizontalSpacing(3); + mainLay->setVerticalSpacing(10); + { + mainLay->addWidget(new QLabel(tr("Name:"), this), 0, 0, + Qt::AlignRight | Qt::AlignVCenter); + mainLay->addWidget(m_nameEdit, 0, 1); + + mainLay->addWidget(new QLabel(tr("Type:"), this), 1, 0, + Qt::AlignRight | Qt::AlignVCenter); + mainLay->addWidget(m_typeCombo, 1, 1); + + QVBoxLayout* extraInfoLay = new QVBoxLayout(); + extraInfoLay->setMargin(0); + extraInfoLay->setSpacing(0); + { + extraInfoLay->addWidget(m_textEdit, 1); + + QGridLayout* imgPropLay = new QGridLayout(); + imgPropLay->setMargin(0); + imgPropLay->setHorizontalSpacing(3); + imgPropLay->setVerticalSpacing(10); + { + imgPropLay->addWidget(new QLabel(tr("Path:"), this), 0, 0, + Qt::AlignRight | Qt::AlignVCenter); + imgPropLay->addWidget(m_imgPathField, 0, 1, 1, 2); + + imgPropLay->addWidget(new QLabel(tr("Aspect Ratio:"), this), 1, 0, + Qt::AlignRight | Qt::AlignVCenter); + imgPropLay->addWidget(m_imgARModeCombo, 1, 1); + } + imgPropLay->setColumnStretch(0, 0); + imgPropLay->setColumnStretch(1, 0); + imgPropLay->setColumnStretch(2, 1); + m_imgPropBox->setLayout(imgPropLay); + extraInfoLay->addWidget(m_imgPropBox, 0); + + extraInfoLay->addSpacing(5); + + QGridLayout* fontPropLay = new QGridLayout(); + fontPropLay->setMargin(0); + fontPropLay->setHorizontalSpacing(3); + fontPropLay->setVerticalSpacing(10); + { + fontPropLay->addWidget(new QLabel(tr("Font:"), this), 0, 0, + Qt::AlignRight | Qt::AlignVCenter); + fontPropLay->addWidget(m_fontCombo, 0, 1, 1, 4); + + fontPropLay->addWidget(new QLabel(tr("Max Size:"), this), 1, 0, + Qt::AlignRight | Qt::AlignVCenter); + fontPropLay->addWidget(m_maxFontSizeEdit, 1, 1); + + fontPropLay->addWidget(m_boldButton, 1, 2); + fontPropLay->addWidget(m_italicButton, 1, 3); + + fontPropLay->addWidget(m_fontColorField, 2, 0, 1, 5); + } + fontPropLay->setColumnStretch(0, 0); + fontPropLay->setColumnStretch(1, 0); + fontPropLay->setColumnStretch(2, 0); + fontPropLay->setColumnStretch(3, 0); + fontPropLay->setColumnStretch(4, 1); + m_fontPropBox->setLayout(fontPropLay); + extraInfoLay->addWidget(m_fontPropBox, 0); + } + mainLay->addLayout(extraInfoLay, 2, 0, 1, 2); + } + mainLay->setColumnStretch(0, 0); + mainLay->setColumnStretch(1, 1); + mainLay->setRowStretch(0, 0); + mainLay->setRowStretch(1, 0); + mainLay->setRowStretch(2, 1); + + QWidget* mainWidget = new QWidget(this); + mainWidget->setLayout(mainLay); + addWidget(mainWidget); + + addWidget(new QLabel(tr("No item selected."), this)); + + bool ret = true; + ret = ret && connect(m_nameEdit, SIGNAL(editingFinished()), this, + SLOT(onNameEdited())); + ret = ret && connect(m_maxFontSizeEdit, SIGNAL(editingFinished()), this, + SLOT(onMaxFontSizeEdited())); + ret = ret && connect(m_typeCombo, SIGNAL(activated(int)), this, + SLOT(onTypeComboActivated(int))); + ret = ret && connect(m_textEdit, SIGNAL(textChanged()), this, + SLOT(onFreeTextChanged())); + ret = ret && connect(m_imgPathField, SIGNAL(pathChanged()), this, + SLOT(onImgPathChanged())); + ret = ret && connect(m_fontCombo, SIGNAL(currentFontChanged(const QFont&)), + this, SLOT(onFontComboChanged(const QFont&))); + ret = ret && connect(m_boldButton, SIGNAL(clicked(bool)), this, + SLOT(onBoldButtonClicked(bool))); + ret = ret && connect(m_italicButton, SIGNAL(clicked(bool)), this, + SLOT(onItalicButtonClicked(bool))); + ret = ret && + connect(m_fontColorField, SIGNAL(colorChanged(const TPixel32&, bool)), + this, SLOT(onFontColorChanged(const TPixel32&, bool))); + ret = ret && connect(m_imgARModeCombo, SIGNAL(activated(int)), this, + SLOT(onImgARModeComboActivated())); + assert(ret); +} + +// called on switching the current item +void ItemInfoView::setCurrentItem(int index) { + if (index == -1) { + if (!currentBoardItem()) return; + setCurrentBoardItem(nullptr); + setCurrentIndex(1); // set to "no item seleceted" page. + return; + } + + setCurrentIndex(0); // set to normal page. + + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + if (index >= boardSettings->getItemCount()) return; + + BoardItem* newItem = &(boardSettings->getItem(index)); + if (currentBoardItem() == newItem) return; + + setCurrentBoardItem(newItem); + + // sync + m_nameEdit->setText(newItem->getName()); + m_maxFontSizeEdit->setValue(newItem->getMaximumFontSize()); + m_typeCombo->setCurrentIndex((int)newItem->getType()); + m_textEdit->setText(newItem->getFreeText()); + m_imgPathField->setPath(newItem->getImgPath().getQString()); + m_fontCombo->setCurrentFont(newItem->font()); + m_boldButton->setChecked(newItem->font().bold()); + m_italicButton->setChecked(newItem->font().italic()); + QColor col = newItem->getColor(); + m_fontColorField->setColor( + TPixel32(col.red(), col.green(), col.blue(), col.alpha())); + int ARModeIndex = m_imgARModeCombo->findData(newItem->getImgARMode()); + if (ARModeIndex >= 0) m_imgARModeCombo->setCurrentIndex(ARModeIndex); + + switch (newItem->getType()) { + case BoardItem::FreeText: + m_textEdit->show(); + m_imgPropBox->hide(); + m_fontPropBox->show(); + break; + case BoardItem::Image: + m_textEdit->hide(); + m_imgPropBox->show(); + m_fontPropBox->hide(); + break; + default: + m_textEdit->hide(); + m_imgPropBox->hide(); + m_fontPropBox->show(); + break; + } +} + +void ItemInfoView::onNameEdited() { + assert(currentBoardItem()); + + QString newName = m_nameEdit->text(); + + if (newName.isEmpty()) { + newName = tr("Item"); + m_nameEdit->setText(newName); + } + + if (currentBoardItem()->getName() == newName) return; + + currentBoardItem()->setName(newName); + + emit itemPropertyChanged(true); +} + +void ItemInfoView::onMaxFontSizeEdited() { + assert(currentBoardItem()); + + int maxFontSize = m_maxFontSizeEdit->getValue(); + + if (currentBoardItem()->getMaximumFontSize() == maxFontSize) return; + + currentBoardItem()->setMaximumFontSize(maxFontSize); + + emit itemPropertyChanged(false); +} + +void ItemInfoView::onTypeComboActivated(int) { + assert(currentBoardItem()); + + BoardItem::Type newType = (BoardItem::Type)m_typeCombo->currentIndex(); + + if (currentBoardItem()->getType() == newType) return; + + currentBoardItem()->setType(newType); + + switch (newType) { + case BoardItem::FreeText: + m_textEdit->show(); + m_imgPropBox->hide(); + m_fontPropBox->show(); + break; + case BoardItem::Image: + m_textEdit->hide(); + m_imgPropBox->show(); + m_fontPropBox->hide(); + break; + default: + m_textEdit->hide(); + m_imgPropBox->hide(); + m_fontPropBox->show(); + break; + } + + emit itemPropertyChanged(true); +} + +void ItemInfoView::onFreeTextChanged() { + assert(currentBoardItem()); + + currentBoardItem()->setFreeText(m_textEdit->toPlainText()); + + emit itemPropertyChanged(false); +} + +void ItemInfoView::onImgPathChanged() { + assert(currentBoardItem()); + TFilePath fp(m_imgPathField->getPath()); + if (fp.isLevelName()) { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + TLevelReaderP lr(scene->decodeFilePath(fp)); + TLevelP level; + if (lr) level = lr->loadInfo(); + if (level.getPointer() && level->getTable()->size() > 0) { + TFrameId firstFrame = level->begin()->first; + fp = fp.withFrame(firstFrame); + m_imgPathField->setPath(fp.getQString()); + } + } + currentBoardItem()->setImgPath(fp); + + emit itemPropertyChanged(true); +} + +void ItemInfoView::onFontComboChanged(const QFont& newFont) { + assert(currentBoardItem()); + + currentBoardItem()->font().setFamily(newFont.family()); + + emit itemPropertyChanged(false); +} + +void ItemInfoView::onBoldButtonClicked(bool on) { + assert(currentBoardItem()); + + currentBoardItem()->font().setBold(on); + + emit itemPropertyChanged(false); +} + +void ItemInfoView::onItalicButtonClicked(bool on) { + assert(currentBoardItem()); + + currentBoardItem()->font().setItalic(on); + + emit itemPropertyChanged(false); +} + +void ItemInfoView::onFontColorChanged(const TPixel32& color, bool isDragging) { + assert(currentBoardItem()); + + if (isDragging) return; + + QColor newColor((int)color.r, (int)color.g, (int)color.b, (int)color.m); + if (currentBoardItem()->getColor() == newColor) return; + currentBoardItem()->setColor(newColor); + + emit itemPropertyChanged(true); +} + +void ItemInfoView::onImgARModeComboActivated() { + assert(currentBoardItem()); + + currentBoardItem()->setImgARMode( + (Qt::AspectRatioMode)m_imgARModeCombo->currentData().toInt()); + + emit itemPropertyChanged(false); +} + +//============================================================================= + +ItemListView::ItemListView(QWidget* parent) : QWidget(parent) { + QPushButton* newItemBtn = + new QPushButton(QIcon(":Resources/plus.svg"), tr("Add"), this); + m_deleteItemBtn = + new QPushButton(QIcon(":Resources/delete_on.svg"), tr("Remove"), this); + m_moveUpBtn = + new QPushButton(QIcon(":Resources/up.svg"), tr("Move Up"), this); + m_moveDownBtn = + new QPushButton(QIcon(":Resources/down.svg"), tr("Move Down"), this); + + m_list = new QListWidget(this); + + QSize iconSize(20, 20); + + newItemBtn->setIconSize(iconSize); + m_deleteItemBtn->setIconSize(iconSize); + m_moveUpBtn->setIconSize(iconSize); + m_moveDownBtn->setIconSize(iconSize); + + m_list->setIconSize(QSize(20, 20)); + m_list->setAlternatingRowColors(true); + m_list->setMaximumWidth(225); + + QHBoxLayout* mainLay = new QHBoxLayout(); + mainLay->setMargin(5); + mainLay->setSpacing(5); + { + QVBoxLayout* buttonsLay = new QVBoxLayout(); + buttonsLay->setMargin(0); + buttonsLay->setSpacing(3); + { + buttonsLay->addWidget(newItemBtn, 0); + buttonsLay->addWidget(m_deleteItemBtn, 0); + buttonsLay->addWidget(m_moveUpBtn, 0); + buttonsLay->addWidget(m_moveDownBtn, 0); + buttonsLay->addStretch(1); + } + mainLay->addLayout(buttonsLay, 0); + + mainLay->addWidget(m_list, 1); + } + setLayout(mainLay); + + bool ret = true; + ret = ret && connect(m_list, SIGNAL(currentRowChanged(int)), this, + SLOT(onCurrentItemSwitched(int))); + ret = ret && connect(newItemBtn, SIGNAL(clicked(bool)), this, + SLOT(onNewItemButtonClicked())); + ret = ret && connect(m_deleteItemBtn, SIGNAL(clicked(bool)), this, + SLOT(onDeleteItemButtonClicked())); + ret = ret && connect(m_moveUpBtn, SIGNAL(clicked(bool)), this, + SLOT(onMoveUpButtonClicked())); + ret = ret && connect(m_moveDownBtn, SIGNAL(clicked(bool)), this, + SLOT(onMoveDownButtonClicked())); + assert(ret); +} + +void ItemListView::initialize() { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + // first, clear all the list items + m_list->clear(); + + if (boardSettings->getItemCount() == 0) return; + + for (int i = 0; i < boardSettings->getItemCount(); i++) { + BoardItem* item = &(boardSettings->getItem(i)); + QListWidgetItem* listItem = new QListWidgetItem(m_list); + + editListWidgetItem(listItem, item); + } + + // this will update information view + m_list->setCurrentRow(0, QItemSelectionModel::ClearAndSelect); +} + +// called when the infoView is edited +void ItemListView::updateCurrentItem() { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + int currentItemIndex = m_list->currentRow(); + + if (currentItemIndex < 0 || currentItemIndex >= boardSettings->getItemCount()) + return; + + BoardItem* item = &(boardSettings->getItem(currentItemIndex)); + editListWidgetItem(m_list->item(currentItemIndex), item); +} + +void ItemListView::onCurrentItemSwitched(int currentRow) { + if (currentRow == -1) { + m_moveUpBtn->setEnabled(false); + m_moveDownBtn->setEnabled(false); + } else { + m_moveUpBtn->setEnabled(currentRow != 0); + m_moveDownBtn->setEnabled(currentRow != m_list->count() - 1); + } + emit currentItemSwitched(currentRow); +} + +void ItemListView::onNewItemButtonClicked() { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + boardSettings->addNewItem(); + + QListWidgetItem* listItem = new QListWidgetItem(); + BoardItem* item = &(boardSettings->getItem(0)); + + editListWidgetItem(listItem, item); + + m_list->insertItem(0, listItem); + m_list->setCurrentRow(0, QItemSelectionModel::ClearAndSelect); + + m_deleteItemBtn->setEnabled(true); + + emit itemAddedOrDeleted(); +} + +void ItemListView::onDeleteItemButtonClicked() { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + int currentRow = m_list->currentRow(); + + assert(currentRow != -1); + + boardSettings->removeItem(currentRow); + + if (m_list->count() == 1) { + m_deleteItemBtn->setEnabled(false); + m_list->setCurrentRow(-1, QItemSelectionModel::ClearAndSelect); + } else if (currentRow == m_list->count() - 1) + m_list->setCurrentRow(m_list->count() - 2, + QItemSelectionModel::ClearAndSelect); + + delete m_list->takeItem(currentRow); + + emit itemAddedOrDeleted(); +} + +void ItemListView::onMoveUpButtonClicked() { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + int currentRow = m_list->currentRow(); + assert(currentRow > 0); + + boardSettings->swapItems(currentRow - 1, currentRow); + + m_list->insertItem(currentRow - 1, m_list->takeItem(currentRow)); + m_list->setCurrentRow(currentRow - 1); + + emit itemAddedOrDeleted(); +} + +void ItemListView::onMoveDownButtonClicked() { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + int currentRow = m_list->currentRow(); + assert(currentRow < m_list->count() - 1); + + boardSettings->swapItems(currentRow, currentRow + 1); + + QListWidgetItem* item = m_list->takeItem(currentRow); + m_list->insertItem(currentRow + 1, item); + m_list->setCurrentRow(currentRow + 1); + + emit itemAddedOrDeleted(); +} + +//============================================================================= + +BoardSettingsPopup::BoardSettingsPopup(QWidget* parent) + : DVGui::Dialog(parent, true, false, "ClapperboardSettings") { + setWindowTitle(tr("Clapperboard Settings")); + + initializeItemTypeString(); + + m_boardView = new BoardView(this); + m_itemInfoView = new ItemInfoView(this); + m_itemListView = new ItemListView(this); + + m_durationEdit = new DVGui::IntLineEdit(this, 1, 0); + + QPushButton* loadPresetBtn = + new QPushButton(QIcon(":Resources/load_on.svg"), tr("Load Preset"), this); + QPushButton* savePresetBtn = new QPushButton(QIcon(":Resources/save_on.svg"), + tr("Save as Preset"), this); + + QPushButton* closeButton = new QPushButton(tr("Close"), this); + + //--- layout + + QHBoxLayout* mainLay = new QHBoxLayout(); + mainLay->setMargin(0); + mainLay->setSpacing(10); + { + QVBoxLayout* leftLay = new QVBoxLayout(); + leftLay->setMargin(0); + leftLay->setSpacing(0); + { + QHBoxLayout* leftTopLay = new QHBoxLayout(); + leftTopLay->setMargin(5); + leftTopLay->setSpacing(3); + { + leftTopLay->addWidget(new QLabel(tr("Duration (frames):"), this), 0); + leftTopLay->addWidget(m_durationEdit, 0); + + leftTopLay->addSpacing(10); + + leftTopLay->addWidget(loadPresetBtn, 0); + leftTopLay->addWidget(savePresetBtn, 0); + + leftTopLay->addStretch(1); + } + leftLay->addLayout(leftTopLay, 0); + + leftLay->addWidget(m_boardView, 1); + } + mainLay->addLayout(leftLay, 1); + + QVBoxLayout* rightLay = new QVBoxLayout(); + rightLay->setMargin(0); + rightLay->setSpacing(15); + { + rightLay->addWidget(m_itemInfoView, 0); + rightLay->addWidget(m_itemListView, 1); + } + mainLay->addLayout(rightLay, 0); + } + m_topLayout->addLayout(mainLay, 1); + + addButtonBarWidget(closeButton); + + bool ret = true; + ret = ret && connect(m_itemListView, SIGNAL(currentItemSwitched(int)), this, + SLOT(onCurrentItemSwitched(int))); + ret = ret && connect(m_itemListView, SIGNAL(itemAddedOrDeleted()), this, + SLOT(onItemAddedOrDeleted())); + ret = ret && connect(m_itemInfoView, SIGNAL(itemPropertyChanged(bool)), this, + SLOT(onItemPropertyChanged(bool))); + ret = ret && connect(m_durationEdit, SIGNAL(editingFinished()), this, + SLOT(onDurationEdited())); + ret = ret && connect(closeButton, SIGNAL(pressed()), this, SLOT(close())); + ret = ret && + connect(loadPresetBtn, SIGNAL(pressed()), this, SLOT(onLoadPreset())); + ret = ret && + connect(savePresetBtn, SIGNAL(pressed()), this, SLOT(onSavePreset())); + + assert(ret); +} + +void BoardSettingsPopup::initialize() { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + m_durationEdit->setValue(boardSettings->getDuration()); + + m_itemListView->initialize(); + + m_boardView->invalidate(); + m_boardView->update(); +} + +void BoardSettingsPopup::initializeItemTypeString() { + if (!stringByItemType.isEmpty()) return; + + stringByItemType[BoardItem::FreeText] = tr("Text"); // free text (m_text) + stringByItemType[BoardItem::ProjectName] = tr("Project name"); + stringByItemType[BoardItem::SceneName] = tr("Scene name"); + stringByItemType[BoardItem::Duration_Frame] = tr("Duration : Frame"); + stringByItemType[BoardItem::Duration_SecFrame] = tr("Duration : Sec + Frame"); + stringByItemType[BoardItem::Duration_HHMMSSFF] = tr("Duration : HH:MM:SS:FF"); + stringByItemType[BoardItem::CurrentDate] = tr("Current date"); + stringByItemType[BoardItem::CurrentDateTime] = tr("Current date and time"); + stringByItemType[BoardItem::UserName] = tr("User name"); + stringByItemType[BoardItem::ScenePath_Aliased] = + tr("Scene location : Aliased path"); + stringByItemType[BoardItem::ScenePath_Full] = + tr("Scene location : Full path"); + stringByItemType[BoardItem::MoviePath_Aliased] = + tr("Output location : Aliased path"); + stringByItemType[BoardItem::MoviePath_Full] = + tr("Output location : Full path"); + stringByItemType[BoardItem::Image] = tr("Image"); // m_imgPath +} + +void BoardSettingsPopup::hideEvent(QHideEvent* event) { + setCurrentBoardItem(nullptr); +} + +// called on changing the current row of ItemListView +void BoardSettingsPopup::onCurrentItemSwitched(int index) { + // updat Info + m_itemInfoView->setCurrentItem(index); + + m_boardView->update(); +} + +void BoardSettingsPopup::onItemAddedOrDeleted() { + m_boardView->invalidate(); + m_boardView->update(); +} + +// called on modifying the infoView +void BoardSettingsPopup::onItemPropertyChanged(bool updateListView) { + m_boardView->invalidate(); + m_boardView->update(); + + if (updateListView) m_itemListView->updateCurrentItem(); +} + +void BoardSettingsPopup::onDurationEdited() { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + boardSettings->setDuration(m_durationEdit->getValue()); + + m_boardView->update(); +} + +void BoardSettingsPopup::onLoadPreset() { + LoadBoardPresetFilePopup popup; + + TFilePath fp = popup.getPath(); + if (fp.isEmpty()) return; + + TIStream is(fp); + if (!is) throw TException(fp.getWideString() + L": Can't open file"); + try { + std::string tagName = ""; + if (!is.matchTag(tagName)) throw TException("Bad file format"); + if (tagName == "clapperboardSettingsPreset") { + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = + scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + boardSettings->loadData(is); + } else + throw TException("Bad file format"); + } catch (const TSystemException& se) { + DVGui::warning(QString::fromStdWString(se.getMessage())); + } catch (...) { + DVGui::error(QObject::tr("Couldn't load %1").arg(fp.getQString())); + } + + initialize(); +} + +void BoardSettingsPopup::onSavePreset() { + SaveBoardPresetFilePopup popup; + + TFilePath fp = popup.getPath(); + if (fp.isEmpty()) return; + + try { + TFileStatus fs(fp); + if (fs.doesExist() && !fs.isWritable()) { + throw TSystemException( + fp, "The preset cannot be saved: it is a read only file."); + } + + TOStream os(fp, false); + if (!os.checkStatus()) throw TException("Could not open file"); + + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* outProp = scene->getProperties()->getOutputProperties(); + BoardSettings* boardSettings = outProp->getBoardSettings(); + + os.openChild("clapperboardSettingsPreset"); + boardSettings->saveData(os, true); + os.closeChild(); + + bool status = os.checkStatus(); + if (!status) throw TException("Could not complete the save preset"); + + } catch (const TSystemException& se) { + DVGui::warning(QString::fromStdWString(se.getMessage())); + } catch (...) { + DVGui::error(QObject::tr("Couldn't save %1").arg(fp.getQString())); + } +} + +//============================================================================= + +SaveBoardPresetFilePopup::SaveBoardPresetFilePopup() + : GenericSaveFilePopup(tr("Save Clapperboard Settings As Preset")) { + m_browser->enableGlobalSelection(false); + setFilterTypes(QStringList("clapperboard")); +} + +void SaveBoardPresetFilePopup::showEvent(QShowEvent* e) { + FileBrowserPopup::showEvent(e); + setFolder(ToonzFolder::getLibraryFolder() + "clapperboards"); +} + +//============================================================================= + +LoadBoardPresetFilePopup::LoadBoardPresetFilePopup() + : GenericLoadFilePopup(tr("Load Clapperboard Settings Preset")) { + m_browser->enableGlobalSelection(false); + setFilterTypes(QStringList("clapperboard")); +} + +void LoadBoardPresetFilePopup::showEvent(QShowEvent* e) { + FileBrowserPopup::showEvent(e); + setFolder(ToonzFolder::getLibraryFolder() + "clapperboards"); +} \ No newline at end of file diff --git a/toonz/sources/toonz/boardsettingspopup.h b/toonz/sources/toonz/boardsettingspopup.h new file mode 100644 index 0000000..fb86d46 --- /dev/null +++ b/toonz/sources/toonz/boardsettingspopup.h @@ -0,0 +1,175 @@ +#pragma once + +#ifndef BOARDSETTINGSPOPUP_H +#define BOARDSETTINGSPOPUP_H + +#include "toonzqt/dvdialog.h" +#include "tpixel.h" +#include "filebrowserpopup.h" +#include +#include + +class TOutputProperties; +class QLineEdit; +class QTextEdit; +class QComboBox; +class QFontComboBox; +class QListWidget; +class BoardItem; + +namespace DVGui { +class FileField; +class ColorField; +class IntLineEdit; +} + +//============================================================================= + +class BoardView : public QWidget { + Q_OBJECT + + enum DragItem { + None = 0, + Translate, + TopLeftCorner, + TopRightCorner, + BottomRightCorner, + BottomLeftCorner, + TopEdge, + RightEdge, + BottomEdge, + LeftEdge + } m_dragItem = None; + + QImage m_boardImg; + bool m_valid = false; + + QRectF m_boardImgRect; + + QRectF m_dragStartItemRect; + QPointF m_dragStartPos; + +public: + BoardView(QWidget* parent = nullptr); + void invalidate() { m_valid = false; } + +protected: + void paintEvent(QPaintEvent* event) override; + void resizeEvent(QResizeEvent* event) override; + + void mouseMoveEvent(QMouseEvent* event) override; + void mousePressEvent(QMouseEvent* event) override; + void mouseReleaseEvent(QMouseEvent* event) override; +}; + +//============================================================================= + +class ItemInfoView : public QStackedWidget { + Q_OBJECT + + QLineEdit* m_nameEdit; + DVGui::IntLineEdit* m_maxFontSizeEdit; + QComboBox* m_typeCombo; + QTextEdit* m_textEdit; + DVGui::FileField* m_imgPathField; + QFontComboBox* m_fontCombo; + QPushButton *m_boldButton, *m_italicButton; + DVGui::ColorField* m_fontColorField; + QComboBox* m_imgARModeCombo; + + QWidget *m_fontPropBox, *m_imgPropBox; + +public: + ItemInfoView(QWidget* parent = nullptr); + void setCurrentItem(int index); + +protected slots: + void onNameEdited(); + void onMaxFontSizeEdited(); + void onTypeComboActivated(int); + void onFreeTextChanged(); + void onImgPathChanged(); + void onFontComboChanged(const QFont&); + void onBoldButtonClicked(bool); + void onItalicButtonClicked(bool); + void onFontColorChanged(const TPixel32&, bool); + void onImgARModeComboActivated(); + +signals: + // if updateListView is true then update the list view as well + void itemPropertyChanged(bool updateListView); +}; + +//============================================================================= + +class ItemListView : public QWidget { + Q_OBJECT + QListWidget* m_list; + QPushButton *m_deleteItemBtn, *m_moveUpBtn, *m_moveDownBtn; + +public: + ItemListView(QWidget* parent = nullptr); + void initialize(); + void updateCurrentItem(); +protected slots: + void onCurrentItemSwitched(int); + void onNewItemButtonClicked(); + void onDeleteItemButtonClicked(); + void onMoveUpButtonClicked(); + void onMoveDownButtonClicked(); +signals: + void currentItemSwitched(int); + void itemAddedOrDeleted(); +}; + +//============================================================================= + +class BoardSettingsPopup : public DVGui::Dialog { + Q_OBJECT + + BoardView* m_boardView; + ItemInfoView* m_itemInfoView; + ItemListView* m_itemListView; + + DVGui::IntLineEdit* m_durationEdit; + + void initialize(); + void initializeItemTypeString(); // call once on the first launch +public: + static BoardItem* currentBoardItem; + + BoardSettingsPopup(QWidget* parent = nullptr); + +protected: + void showEvent(QShowEvent*) override { initialize(); } + void hideEvent(QHideEvent*) override; +protected slots: + void onCurrentItemSwitched(int); + void onItemAddedOrDeleted(); + void onItemPropertyChanged(bool updateListView); + void onDurationEdited(); + void onLoadPreset(); + void onSavePreset(); +}; + +//============================================================================= + +class SaveBoardPresetFilePopup final : public GenericSaveFilePopup { +public: + SaveBoardPresetFilePopup(); + +protected: + void showEvent(QShowEvent*) override; +}; + +//============================================================================= + +class LoadBoardPresetFilePopup final : public GenericLoadFilePopup { +public: + LoadBoardPresetFilePopup(); + +protected: + void showEvent(QShowEvent*) override; +}; + +#endif diff --git a/toonz/sources/toonz/castviewer.cpp b/toonz/sources/toonz/castviewer.cpp index 78182bc..14ba6d3 100644 --- a/toonz/sources/toonz/castviewer.cpp +++ b/toonz/sources/toonz/castviewer.cpp @@ -17,7 +17,6 @@ #include "toonz/txshlevelhandle.h" #include "toonz/levelset.h" #include "toonz/toonzscene.h" -#include "toonz/levelset.h" #include "toonz/txshsimplelevel.h" #include "toonz/txshleveltypes.h" diff --git a/toonz/sources/toonz/cellkeyframeselection.cpp b/toonz/sources/toonz/cellkeyframeselection.cpp index aff0068..a10a75a 100644 --- a/toonz/sources/toonz/cellkeyframeselection.cpp +++ b/toonz/sources/toonz/cellkeyframeselection.cpp @@ -71,7 +71,9 @@ void TCellKeyframeSelection::copyCellsKeyframes() { QClipboard *clipboard = QApplication::clipboard(); TXsheet *xsh = m_xsheetHandle->getXsheet(); TKeyframeData *keyframeData = new TKeyframeData(); - keyframeData->setKeyframes(m_keyframeSelection->getSelection(), xsh); + TKeyframeData::Position startPos(r0, c0); + keyframeData->setKeyframes(m_keyframeSelection->getSelection(), xsh, + startPos); data->setKeyframeData(keyframeData); } // Set the cliboard @@ -113,8 +115,8 @@ void TCellKeyframeSelection::selectCellsKeyframes(int r0, int c0, int r1, m_cellSelection->selectCells(r0, c0, r1, c1); TXsheet *xsh = m_xsheetHandle->getXsheet(); m_xsheetHandle->getXsheet(); - if (r1 < r0) tswap(r0, r1); - if (c1 < c0) tswap(c0, c1); + if (r1 < r0) std::swap(r0, r1); + if (c1 < c0) std::swap(c0, c1); m_keyframeSelection->clear(); int r, c; for (c = c0; c <= c1; c++) diff --git a/toonz/sources/toonz/cellselection.cpp b/toonz/sources/toonz/cellselection.cpp index 381e800..3c23b5e 100644 --- a/toonz/sources/toonz/cellselection.cpp +++ b/toonz/sources/toonz/cellselection.cpp @@ -119,6 +119,7 @@ void deleteCellsWithoutUndo(int &r0, int &c0, int &r1, int &c1) { xsh->clearCells(r0, c, r1 - r0 + 1); TXshColumn *column = xsh->getColumn(c); if (column && column->isEmpty()) { + column->resetColumnProperties(); TFx *fx = column->getFx(); if (fx) { int i; @@ -144,6 +145,7 @@ void cutCellsWithoutUndo(int &r0, int &c0, int &r1, int &c1) { xsh->removeCells(r0, c, r1 - r0 + 1); TXshColumn *column = xsh->getColumn(c); if (column && column->isEmpty()) { + column->resetColumnProperties(); TFx *fx = column->getFx(); if (!fx) continue; int i; @@ -1251,6 +1253,62 @@ public: //----------------------------------------------------------------------------- }; +//============================================================================= +// Duplicate in XSheet Undo +//----------------------------------------------------------------------------- + +class DuplicateInXSheetUndo final : public TUndo { + int m_r0, m_r1, m_c; + TXshCell m_oldCell; + TXshCell m_newCell; + bool m_goForward; + +public: + DuplicateInXSheetUndo(int r0, int r1, int c, TXshCell oldCell, + TXshCell newCell, bool goForward) + : m_r0(r0) + , m_r1(r1) + , m_c(c) + , m_oldCell(oldCell) + , m_newCell(newCell) + , m_goForward(goForward) {} + + ~DuplicateInXSheetUndo() {} + + void undo() const override { + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + if (m_r1 > m_r0) { + for (int i = m_r0; i <= m_r1; i++) { + xsh->setCell(i, m_c, m_oldCell); + } + } else + xsh->setCell(m_r0, m_c, m_oldCell); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + if (m_goForward) CommandManager::instance()->execute(MI_PrevFrame); + } + + void redo() const override { + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + if (m_r1 > m_r0) { + for (int i = m_r0; i <= m_r1; i++) { + xsh->setCell(i, m_c, m_newCell); + } + } else + xsh->setCell(m_r0, m_c, m_newCell); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + if (m_goForward) CommandManager::instance()->execute(MI_NextFrame); + } + + int getSize() const override { return sizeof(*this); } + + QString getHistoryString() override { + return QObject::tr("Duplicate Frame in XSheet"); + } + + int getHistoryType() override { return HistoryType::Xsheet; } + //----------------------------------------------------------------------------- +}; + } // namespace //----------------------------------------------------------------------------- @@ -1335,6 +1393,7 @@ void TCellSelection::enableCommands() { &TCellSelection::reframeWithEmptyInbetweens); enableCommand(this, MI_PasteNumbers, &TCellSelection::overwritePasteNumbers); + enableCommand(this, MI_Duplicate, &TCellSelection::duplicateFrame); } //----------------------------------------------------------------------------- // Used in RenameCellField::eventFilter() @@ -1387,8 +1446,8 @@ bool TCellSelection::isEmpty() const { return m_range.isEmpty(); } //----------------------------------------------------------------------------- void TCellSelection::selectCells(int r0, int c0, int r1, int c1) { - if (r0 > r1) tswap(r0, r1); - if (c0 > c1) tswap(c0, c1); + if (r0 > r1) std::swap(r0, r1); + if (c0 > c1) std::swap(c0, c1); m_range.m_r0 = r0; m_range.m_c0 = c0; m_range.m_r1 = r1; @@ -1627,9 +1686,11 @@ void TCellSelection::pasteCells() { // (r0,c0) std::set positions; int newC0 = c0; - if (viewer && !viewer->orientation()->isVerticalTimeline()) + if (viewer && !viewer->orientation()->isVerticalTimeline() && !cellData) newC0 = c0 - keyframeData->getColumnSpanCount() + 1; - positions.insert(TKeyframeSelection::Position(r0, newC0)); + TKeyframeSelection::Position offset(keyframeData->getKeyframesOffset()); + positions.insert(TKeyframeSelection::Position(r0 + offset.first, + newC0 + offset.second)); keyframeData->getKeyframes(positions); selection.select(positions); @@ -1849,6 +1910,103 @@ void TCellSelection::pasteKeyframesInto() { //----------------------------------------------------------------------------- +void TCellSelection::duplicateFrame() { + if (!Preferences::instance()->isSyncLevelRenumberWithXsheetEnabled()) { + DVGui::warning( + QObject::tr("Please enable \"Sync Level Strip Drawing Number Changes " + "with the XSheet\" preference option\nto use the duplicate " + "command in the xsheet / timeline.")); + return; + } + + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + // TApp::instance()->getCurrentScene()->getScene()->g + int r0, c0, r1, c1; + getSelectedCells(r0, c0, r1, c1); + // check for cases that won't work + if (c1 > c0) { + DVGui::error( + QObject::tr("Please select only one layer to duplicate a frame.")); + return; + } + if (r1 > r0) { + DVGui::error(QObject::tr("Please select only one frame to duplicate.")); + return; + } + + r0 = TTool::getApplication()->getCurrentFrame()->getFrame(); + c0 = TTool::getApplication()->getCurrentColumn()->getColumnIndex(); + + TXshCell cell = xsh->getCell(r0, c0); + TXshCell prevCell = xsh->getCell(r0 - 1, c0); + TXshCell nextCell = xsh->getCell(r0 + 1, c0); + TFrameId selectedFrameId = cell.getFrameId(); + TXshSimpleLevel *sl = cell.getSimpleLevel(); + bool usePreviousCell = false; + bool goForward = false; + + // check if we use the current cell to duplicate or the previous cell + if (cell.isEmpty()) { + if (prevCell.isEmpty() || !(prevCell.m_level->getSimpleLevel())) { + return; + } + usePreviousCell = true; + selectedFrameId = prevCell.getFrameId(); + sl = prevCell.getSimpleLevel(); + } + if (!sl || sl->isSubsequence() || sl->isReadOnly()) return; + + // check whether to change the next cell or replace the current cell if it is + // a hold from a previous frame + if (!usePreviousCell) { + // use the current cell + if (prevCell.m_level == cell.m_level && + prevCell.m_frameId == cell.m_frameId) { + // the current frame is a hold from a previous frame + // change this frame and any sequential frames part of the same hold + bool hold = true; + r1 = r0 + 1; + while (hold) { + TXshCell testCell = xsh->getCell(r1, c0); + if (testCell.m_frameId == cell.m_frameId && + testCell.m_level == cell.m_level) { + r1 += 1; + } else { + r1 -= 1; + hold = false; + } + } + + } else { + // This is not part of a hold, use the next cell. + // make sure we are not going to overwrite a non-empty cell + if (nextCell.isEmpty()) { + r0 += 1; + cell = nextCell; + goForward = true; + } else + return; + } + } else { + // cell = prevCell; + } + + std::set frames; + frames.insert(selectedFrameId); + TUndoManager::manager()->beginBlock(); + FilmstripCmd::duplicate(sl, frames, true); + TXshCell newCell; + newCell.m_level = sl; + newCell.m_frameId = selectedFrameId + 1; + DuplicateInXSheetUndo *undo = + new DuplicateInXSheetUndo(r0, r1, c0, cell, newCell, goForward); + TUndoManager::manager()->add(undo); + TUndoManager::manager()->endBlock(); + undo->redo(); +} + +//----------------------------------------------------------------------------- + void TCellSelection::openTimeStretchPopup() { if (!m_timeStretchPopup) m_timeStretchPopup = new TimeStretchPopup(); m_timeStretchPopup->show(); diff --git a/toonz/sources/toonz/cellselection.h b/toonz/sources/toonz/cellselection.h index 6adf8d2..fcc03e0 100644 --- a/toonz/sources/toonz/cellselection.h +++ b/toonz/sources/toonz/cellselection.h @@ -109,6 +109,7 @@ public: void convertVectortoVector(); void reframeWithEmptyInbetweens(); + void duplicateFrame(); void renameCells(TXshCell &cell); // rename cells for each columns with correspondent item in the list diff --git a/toonz/sources/toonz/cellselectioncommand.cpp b/toonz/sources/toonz/cellselectioncommand.cpp index e91fa6c..cc78814 100644 --- a/toonz/sources/toonz/cellselectioncommand.cpp +++ b/toonz/sources/toonz/cellselectioncommand.cpp @@ -28,6 +28,8 @@ #include "toonz/hook.h" #include "toonz/levelproperties.h" #include "toonz/childstack.h" +#include "toonz/tframehandle.h" +#include "toonz/tcolumnhandle.h" // TnzCore includes #include "tsystem.h" @@ -43,7 +45,6 @@ // tcg includes #include "tcg/tcg_macros.h" -#include "tcg/tcg_unique_ptr.h" // STD includes #include @@ -352,7 +353,7 @@ class StepUndo final : public TUndo { int m_step; int m_newRows; - tcg::unique_ptr m_cells; + std::unique_ptr m_cells; public: StepUndo(int r0, int c0, int r1, int c1, int step); @@ -381,7 +382,7 @@ StepUndo::StepUndo(int r0, int c0, int r1, int c1, int step) , m_newRows(m_rowsCount * (step - 1)) , m_cells(new TXshCell[m_rowsCount * m_colsCount]) { assert(m_rowsCount > 0 && m_colsCount > 0 && step > 0); - assert(m_cells.get()); + assert(m_cells); int k = 0; for (int r = r0; r <= r1; ++r) @@ -405,7 +406,7 @@ void StepUndo::redo() const { //----------------------------------------------------------------------------- void StepUndo::undo() const { - TCG_ASSERT(m_rowsCount > 0 && m_colsCount > 0 && m_cells.get(), return ); + TCG_ASSERT(m_rowsCount > 0 && m_colsCount > 0 && m_cells, return ); TApp *app = TApp::instance(); TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); @@ -453,7 +454,7 @@ class EachUndo final : public TUndo { int m_each; int m_newRows; - tcg::unique_ptr m_cells; + std::unique_ptr m_cells; public: EachUndo(int r0, int c0, int r1, int c1, int each); @@ -483,7 +484,7 @@ EachUndo::EachUndo(int r0, int c0, int r1, int c1, int each) : m_rowsCount / each) , m_cells(new TXshCell[m_rowsCount * m_colsCount]) { assert(m_rowsCount > 0 && m_colsCount > 0 && each > 0); - assert(m_cells.get()); + assert(m_cells); int k = 0; for (int r = r0; r <= r1; ++r) @@ -507,7 +508,7 @@ void EachUndo::redo() const { //----------------------------------------------------------------------------- void EachUndo::undo() const { - TCG_ASSERT(m_rowsCount > 0 && m_colsCount > 0 && m_cells.get(), return ); + TCG_ASSERT(m_rowsCount > 0 && m_colsCount > 0 && m_cells, return ); TApp *app = TApp::instance(); TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); @@ -798,7 +799,7 @@ class ResetStepUndo final : public TUndo { int m_r0, m_c0, m_r1, m_c1; int m_rowsCount, m_colsCount; - tcg::unique_ptr m_cells; + std::unique_ptr m_cells; QMap m_insertedCells; //!< Count of inserted cells, by column public: @@ -821,7 +822,7 @@ ResetStepUndo::ResetStepUndo(int r0, int c0, int r1, int c1) , m_colsCount(m_c1 - m_c0 + 1) , m_cells(new TXshCell[m_rowsCount * m_colsCount]) { assert(m_rowsCount > 0 && m_colsCount > 0); - assert(m_cells.get()); + assert(m_cells); TApp *app = TApp::instance(); @@ -897,7 +898,7 @@ class IncreaseStepUndo final : public TUndo { int m_r0, m_c0, m_r1, m_c1; int m_rowsCount, m_colsCount; - tcg::unique_ptr m_cells; + std::unique_ptr m_cells; QMap m_insertedCells; public: @@ -923,7 +924,7 @@ IncreaseStepUndo::IncreaseStepUndo(int r0, int c0, int r1, int c1) , m_colsCount(m_c1 - m_c0 + 1) , m_cells(new TXshCell[m_rowsCount * m_colsCount]) , m_newR1(m_r1) { - assert(m_cells.get()); + assert(m_cells); int k = 0; for (int c = c0; c <= c1; ++c) { @@ -977,7 +978,19 @@ void IncreaseStepUndo::undo() const { //============================================================================= void TCellSelection::increaseStepCells() { - if (isEmpty() || areAllColSelectedLocked()) return; + if (isEmpty()) { + int row = TTool::getApplication()->getCurrentFrame()->getFrame(); + int col = TTool::getApplication()->getCurrentColumn()->getColumnIndex(); + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + m_range.m_r0 = row; + m_range.m_r1 = row; + m_range.m_c0 = col; + m_range.m_c1 = col; + TXshCell cell; + cell = xsh->getCell(row, col); + if (cell.isEmpty()) return; + } + if (areAllColSelectedLocked()) return; IncreaseStepUndo *undo = new IncreaseStepUndo(m_range.m_r0, m_range.m_c0, m_range.m_r1, m_range.m_c1); @@ -1001,7 +1014,7 @@ class DecreaseStepUndo final : public TUndo { int m_r0, m_c0, m_r1, m_c1; int m_rowsCount, m_colsCount; - tcg::unique_ptr m_cells; + std::unique_ptr m_cells; QMap m_removedCells; public: @@ -1027,7 +1040,7 @@ DecreaseStepUndo::DecreaseStepUndo(int r0, int c0, int r1, int c1) , m_colsCount(m_c1 - m_c0 + 1) , m_cells(new TXshCell[m_rowsCount * m_colsCount]) , m_newR1(m_r1) { - assert(m_cells.get()); + assert(m_cells); int k = 0; for (int c = c0; c <= c1; ++c) { @@ -1090,6 +1103,31 @@ void DecreaseStepUndo::undo() const { //============================================================================= void TCellSelection::decreaseStepCells() { + if (isEmpty()) { + int row = TTool::getApplication()->getCurrentFrame()->getFrame(); + int col = TTool::getApplication()->getCurrentColumn()->getColumnIndex(); + int r1 = row; + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + TXshCell cell; + TXshCell nextCell; + bool sameCells = true; + cell = xsh->getCell(row, col); + if (cell.isEmpty()) return; + + for (int i = 1; sameCells; i++) { + nextCell = xsh->getCell(row + i, col); + if (nextCell.m_frameId == cell.m_frameId && + nextCell.m_level == cell.m_level) { + r1 = row + i; + } else + sameCells = false; + } + m_range.m_r0 = row; + m_range.m_r1 = r1; + m_range.m_c0 = col; + m_range.m_c1 = col; + TApp::instance()->getCurrentSelection()->notifySelectionChanged(); + } DecreaseStepUndo *undo = new DecreaseStepUndo(m_range.m_r0, m_range.m_c0, m_range.m_r1, m_range.m_c1); TUndoManager::manager()->add(undo); diff --git a/toonz/sources/toonz/colormodelviewer.cpp b/toonz/sources/toonz/colormodelviewer.cpp index 9ac1d77..dd6c463 100644 --- a/toonz/sources/toonz/colormodelviewer.cpp +++ b/toonz/sources/toonz/colormodelviewer.cpp @@ -260,14 +260,14 @@ void ColorModelViewer::contextMenuEvent(QContextMenuEvent *event) { /*! If left button is pressed recall \b pick() in event pos. */ void ColorModelViewer::mousePressEvent(QMouseEvent *event) { - if (event->button() == Qt::LeftButton) pick(event->pos()); + if (event->button() == Qt::LeftButton) pick(event->pos() * getDevPixRatio()); } //----------------------------------------------------------------------------- /*! If left button is moved recall \b pick() in event pos. */ void ColorModelViewer::mouseMoveEvent(QMouseEvent *event) { - if (event->buttons() & Qt::LeftButton) pick(event->pos()); + if (event->buttons() & Qt::LeftButton) pick(event->pos() * getDevPixRatio()); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/columncommand.cpp b/toonz/sources/toonz/columncommand.cpp index a6cf920..ad92e0c 100644 --- a/toonz/sources/toonz/columncommand.cpp +++ b/toonz/sources/toonz/columncommand.cpp @@ -45,6 +45,8 @@ #include "tstroke.h" #include "tundo.h" +#include "tools/toolhandle.h" + // Qt includes #include #include @@ -1235,6 +1237,10 @@ public: TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); int cc = TApp::instance()->getCurrentColumn()->getColumnIndex(); bool sound_changed = false; + TTool *tool = TApp::instance()->getCurrentTool()->getTool(); + TTool::Viewer *viewer = tool ? tool->getViewer() : nullptr; + bool viewer_changed = false; + for (int i = 0; i < xsh->getColumnCount(); i++) { /*- 空のカラムの場合は飛ばす -*/ if (xsh->isColumnEmpty(i)) continue; @@ -1263,6 +1269,7 @@ public: column->lock(negate); else column->lock(!column->isLocked()); + viewer_changed = true; } if (cmd & (CMD_ENABLE_PREVIEW | CMD_DISABLE_PREVIEW | CMD_TOGGLE_PREVIEW)) { @@ -1282,6 +1289,7 @@ public: else column->setCamstandVisible(!column->isCamstandVisible()); if (column->getSoundColumn()) sound_changed = true; + viewer_changed = true; } /*TAB if(cmd & (CMD_ENABLE_PREVIEW|CMD_DISABLE_PREVIEW|CMD_TOGGLE_PREVIEW)) @@ -1308,6 +1316,7 @@ column->setCamstandVisible(!column->isCamstandVisible()); TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged(); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); TApp::instance()->getCurrentScene()->setDirtyFlag(true); + if (viewer && viewer_changed) viewer->invalidateToolStatus(); } }; diff --git a/toonz/sources/toonz/columnselection.cpp b/toonz/sources/toonz/columnselection.cpp index aded4f4..4bd705e 100644 --- a/toonz/sources/toonz/columnselection.cpp +++ b/toonz/sources/toonz/columnselection.cpp @@ -16,6 +16,7 @@ #include "toonz/txshleveltypes.h" #include "toonz/txshsimplelevel.h" #include "toonz/txshcell.h" +#include "toonz/levelproperties.h" #include "orientation.h" // TnzCore includes @@ -128,6 +129,9 @@ void TColumnSelection::explodeChild() { static bool canMergeColumns(int column, int mColumn, bool forMatchlines) { TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + + if (xsh->getColumn(column)->isLocked()) return false; + int start, end; xsh->getCellRange(column, start, end); @@ -164,6 +168,13 @@ static bool canMergeColumns(int column, int mColumn, bool forMatchlines) { if (level->getType() != mLevel->getType()) return false; if (level->getType() != PLI_XSHLEVEL && level->getType() != OVL_XSHLEVEL) return false; + // Check level type write support. Based on TTool::updateEnabled() + if (level->getType() == OVL_XSHLEVEL && + (level->getPath().getType() == "psd" || // PSD files. + level->is16BitChannelLevel() || // 16bpc images. + level->getProperties()->getBpp() == 1)) { // Black & White images. + return false; + } } } return true; diff --git a/toonz/sources/toonz/comboviewerpane.cpp b/toonz/sources/toonz/comboviewerpane.cpp index b69a20c..f0c4a5d 100644 --- a/toonz/sources/toonz/comboviewerpane.cpp +++ b/toonz/sources/toonz/comboviewerpane.cpp @@ -13,7 +13,6 @@ #include "toonz/tframehandle.h" #include "toonz/tcolumnhandle.h" #include "toonz/txshlevelhandle.h" -#include "toonz/txsheethandle.h" #include "toonz/toonzscene.h" #include "toonz/sceneproperties.h" #include "toonz/txsheet.h" @@ -86,12 +85,11 @@ ComboViewerPanel::ComboViewerPanel(QWidget *parent, Qt::WindowFlags flags) #else ComboViewerPanel::ComboViewerPanel(QWidget *parent, Qt::WFlags flags) #endif - : StyleShortcutSwitchablePanel(parent) { + : QFrame(parent) { TApp *app = TApp::instance(); - QFrame *hbox = new QFrame(this); - hbox->setFrameStyle(QFrame::StyledPanel); - hbox->setObjectName("ComboViewerPanel"); + setFrameStyle(QFrame::StyledPanel); + setObjectName("ComboViewerPanel"); // ToolBar m_toolbar = new Toolbar(this, false); @@ -152,8 +150,7 @@ ComboViewerPanel::ComboViewerPanel(QWidget *parent, Qt::WFlags flags) new FlipConsole(mainLayout, buttons, false, m_keyFrameButton, "SceneViewerConsole", this, true); } - hbox->setLayout(mainLayout); - setWidget(hbox); + setLayout(mainLayout); m_flipConsole->enableButton(FlipConsole::eMatte, false, false); m_flipConsole->enableButton(FlipConsole::eSave, false, false); @@ -193,22 +190,17 @@ ComboViewerPanel::ComboViewerPanel(QWidget *parent, Qt::WFlags flags) SLOT(update())); ret = ret && connect(app->getCurrentScene(), SIGNAL(sceneSwitched()), this, SLOT(onSceneSwitched())); - ret = ret && connect(m_toolOptions, SIGNAL(newPanelCreated()), this, - SLOT(updateTabFocus())); assert(ret); m_flipConsole->setChecked(FlipConsole::eSound, true); m_playSound = m_flipConsole->isChecked(FlipConsole::eSound); - // note: initializeTitleBar() refers to m_sceneViewer - initializeTitleBar(getTitleBar()); - // initial state of the parts - m_visibleFlag[CVPARTS_TOOLBAR] = true; - m_visibleFlag[CVPARTS_TOOLOPTIONS] = true; - m_visibleFlag[CVPARTS_FLIPCONSOLE] = true; + m_visiblePartsFlag = CVPARTS_ALL; updateShowHide(); + + setFocusProxy(m_sceneViewer); } //----------------------------------------------------------------------------- @@ -217,11 +209,11 @@ ComboViewerPanel::ComboViewerPanel(QWidget *parent, Qt::WFlags flags) void ComboViewerPanel::updateShowHide() { // toolbar - m_toolbar->setVisible(m_visibleFlag[CVPARTS_TOOLBAR]); + m_toolbar->setVisible(m_visiblePartsFlag & CVPARTS_TOOLBAR); // tool options bar - m_toolOptions->setVisible(m_visibleFlag[CVPARTS_TOOLOPTIONS]); + m_toolOptions->setVisible(m_visiblePartsFlag & CVPARTS_TOOLOPTIONS); // flip console - m_flipConsole->showHideAllParts(m_visibleFlag[CVPARTS_FLIPCONSOLE]); + m_flipConsole->showHideAllParts(m_visiblePartsFlag & CVPARTS_FLIPCONSOLE); update(); } @@ -245,16 +237,16 @@ void ComboViewerPanel::addShowHideContextMenu(QMenu *menu) { QAction *flipConsoleSHAct = showHideMenu->addAction(tr("Console")); toolbarSHAct->setCheckable(true); - toolbarSHAct->setChecked(m_visibleFlag[CVPARTS_TOOLBAR]); - toolbarSHAct->setData((int)CVPARTS_TOOLBAR); + toolbarSHAct->setChecked(m_visiblePartsFlag & CVPARTS_TOOLBAR); + toolbarSHAct->setData((UINT)CVPARTS_TOOLBAR); toolOptionsSHAct->setCheckable(true); - toolOptionsSHAct->setChecked(m_visibleFlag[CVPARTS_TOOLOPTIONS]); - toolOptionsSHAct->setData((int)CVPARTS_TOOLOPTIONS); + toolOptionsSHAct->setChecked(m_visiblePartsFlag & CVPARTS_TOOLOPTIONS); + toolOptionsSHAct->setData((UINT)CVPARTS_TOOLOPTIONS); flipConsoleSHAct->setCheckable(true); - flipConsoleSHAct->setChecked(m_visibleFlag[CVPARTS_FLIPCONSOLE]); - flipConsoleSHAct->setData((int)CVPARTS_FLIPCONSOLE); + flipConsoleSHAct->setChecked(m_visiblePartsFlag & CVPARTS_FLIPCONSOLE); + flipConsoleSHAct->setData((UINT)CVPARTS_FLIPCONSOLE); QActionGroup *showHideActGroup = new QActionGroup(this); showHideActGroup->setExclusive(false); @@ -281,13 +273,10 @@ void ComboViewerPanel::addShowHideContextMenu(QMenu *menu) { */ void ComboViewerPanel::onShowHideActionTriggered(QAction *act) { - CV_Parts parts = (CV_Parts)act->data().toInt(); - assert(parts < CVPARTS_COUNT); + CV_Parts part = (CV_Parts)act->data().toUInt(); + assert(part < CVPARTS_End); - if (m_visibleFlag[parts]) - m_visibleFlag[parts] = false; - else - m_visibleFlag[parts] = true; + m_visiblePartsFlag ^= part; updateShowHide(); } @@ -336,15 +325,11 @@ void ComboViewerPanel::onDrawFrame( //----------------------------------------------------------------------------- -ComboViewerPanel::~ComboViewerPanel() { - if (TApp::instance()->getInknPaintViewerPanel() == this) - TApp::instance()->setInknPaintViewerPanel(0); -} +ComboViewerPanel::~ComboViewerPanel() {} //----------------------------------------------------------------------------- void ComboViewerPanel::showEvent(QShowEvent *event) { - StyleShortcutSwitchablePanel::showEvent(event); TApp *app = TApp::instance(); TFrameHandle *frameHandle = app->getCurrentFrame(); TSceneHandle *sceneHandle = app->getCurrentScene(); @@ -374,6 +359,10 @@ void ComboViewerPanel::showEvent(QShowEvent *event) { */ ret = ret && connect(sceneHandle, SIGNAL(nameSceneChanged()), this, SLOT(changeWindowTitle())); + ret = + ret && connect(sceneHandle, SIGNAL(preferenceChanged(const QString &)), + m_flipConsole, SLOT(onPreferenceChanged(const QString &))); + ret = ret && connect(levelHandle, SIGNAL(xshLevelChanged()), this, SLOT(changeWindowTitle())); ret = ret && connect(frameHandle, SIGNAL(frameSwitched()), this, @@ -401,6 +390,7 @@ void ComboViewerPanel::showEvent(QShowEvent *event) { assert(ret); m_flipConsole->setActive(true); + m_flipConsole->onPreferenceChanged(""); // refresh onSceneChanged(); @@ -410,7 +400,6 @@ void ComboViewerPanel::showEvent(QShowEvent *event) { //----------------------------------------------------------------------------- void ComboViewerPanel::hideEvent(QHideEvent *event) { - StyleShortcutSwitchablePanel::hideEvent(event); TApp *app = TApp::instance(); disconnect(app->getCurrentFrame(), 0, this, 0); disconnect(app->getCurrentScene(), 0, this, 0); @@ -420,6 +409,8 @@ void ComboViewerPanel::hideEvent(QHideEvent *event) { disconnect(app->getCurrentTool(), SIGNAL(toolSwitched()), m_sceneViewer, SLOT(onToolSwitched())); + disconnect(app->getCurrentScene(), SIGNAL(preferenceChanged(const QString &)), + m_flipConsole, SLOT(onPreferenceChanged(const QString &))); m_flipConsole->setActive(false); } @@ -437,9 +428,9 @@ void ComboViewerPanel::initializeTitleBar(TPanelTitleBar *titleBar) { // buttons for show / hide toggle for the field guide and the safe area TPanelTitleBarButtonForSafeArea *safeAreaButton = - new TPanelTitleBarButtonForSafeArea(titleBar, ":Resources/pane_safe_off.svg", - ":Resources/pane_safe_over.svg", - ":Resources/pane_safe_on.svg"); + new TPanelTitleBarButtonForSafeArea( + titleBar, ":Resources/pane_safe_off.svg", + ":Resources/pane_safe_over.svg", ":Resources/pane_safe_on.svg"); safeAreaButton->setToolTip(tr("Safe Area (Right Click to Select)")); titleBar->add(QPoint(x, 0), safeAreaButton); ret = ret && connect(safeAreaButton, SIGNAL(toggled(bool)), @@ -508,8 +499,8 @@ void ComboViewerPanel::initializeTitleBar(TPanelTitleBar *titleBar) { // preview toggles m_previewButton = new TPanelTitleBarButton( - titleBar, ":Resources/pane_preview_off.svg", ":Resources/pane_preview_over.svg", - ":Resources/pane_preview_on.svg"); + titleBar, ":Resources/pane_preview_off.svg", + ":Resources/pane_preview_over.svg", ":Resources/pane_preview_on.svg"); x += 10 + iconWidth; titleBar->add(QPoint(x, 0), m_previewButton); m_previewButton->setToolTip(tr("Preview")); @@ -617,6 +608,7 @@ void ComboViewerPanel::changeWindowTitle() { TApp *app = TApp::instance(); ToonzScene *scene = app->getCurrentScene()->getScene(); if (!scene) return; + if (!parentWidget()) return; int frame = app->getCurrentFrame()->getFrame(); // put the titlebar texts in this string @@ -638,7 +630,7 @@ void ComboViewerPanel::changeWindowTitle() { !m_sceneViewer->is3DView()) { name = name + tr(" (Flipped)"); } - setWindowTitle(name); + parentWidget()->setWindowTitle(name); return; } TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); @@ -648,7 +640,7 @@ void ComboViewerPanel::changeWindowTitle() { !m_sceneViewer->is3DView()) { name = name + tr(" (Flipped)"); } - setWindowTitle(name); + parentWidget()->setWindowTitle(name); return; } assert(cell.m_level.getPointer()); @@ -677,7 +669,7 @@ void ComboViewerPanel::changeWindowTitle() { && !CameraTestCheck::instance() // camera test mode must be OFF // neither - ->isEnabled() && + ->isEnabled() && !m_sceneViewer->is3DView()) { TAffine aff = m_sceneViewer->getViewMatrix(); if (m_sceneViewer->getIsFlippedX()) aff = aff * TScale(-1, 1); @@ -713,7 +705,7 @@ void ComboViewerPanel::changeWindowTitle() { !m_sceneViewer->is3DView()) { name = name + tr(" (Flipped)"); } - setWindowTitle(name); + parentWidget()->setWindowTitle(name); } //----------------------------------------------------------------------------- @@ -822,13 +814,6 @@ void ComboViewerPanel::onFrameTypeChanged() { //----------------------------------------------------------------------------- -void ComboViewerPanel::onPreferenceChanged(const QString &prefName) { - m_flipConsole->onPreferenceChanged(prefName); - StyleShortcutSwitchablePanel::onPreferenceChanged(prefName); -} - -//----------------------------------------------------------------------------- - void ComboViewerPanel::playAudioFrame(int frame) { if (m_first) { m_first = false; @@ -861,8 +846,8 @@ bool ComboViewerPanel::hasSoundtrack() { } TXsheetHandle *xsheetHandle = TApp::instance()->getCurrentXsheet(); TXsheet::SoundProperties *prop = new TXsheet::SoundProperties(); - if(!m_sceneViewer->isPreviewEnabled()) prop->m_isPreview = true; - m_sound = xsheetHandle->getXsheet()->makeSound(prop); + if (!m_sceneViewer->isPreviewEnabled()) prop->m_isPreview = true; + m_sound = xsheetHandle->getXsheet()->makeSound(prop); if (m_sound == NULL) { m_hasSoundtrack = false; return false; @@ -876,4 +861,21 @@ void ComboViewerPanel::onButtonPressed(FlipConsole::EGadget button) { if (button == FlipConsole::eSound) { m_playSound = !m_playSound; } +} + +//----------------------------------------------------------------------------- + +void ComboViewerPanel::setVisiblePartsFlag(UINT flag) { + m_visiblePartsFlag = flag; + updateShowHide(); +} + +// SaveLoadQSettings +void ComboViewerPanel::save(QSettings &settings) const { + settings.setValue("visibleParts", m_visiblePartsFlag); +} + +void ComboViewerPanel::load(QSettings &settings) { + m_visiblePartsFlag = settings.value("visibleParts", CVPARTS_ALL).toUInt(); + updateShowHide(); } \ No newline at end of file diff --git a/toonz/sources/toonz/comboviewerpane.h b/toonz/sources/toonz/comboviewerpane.h index b12bef6..614e8f6 100644 --- a/toonz/sources/toonz/comboviewerpane.h +++ b/toonz/sources/toonz/comboviewerpane.h @@ -3,12 +3,14 @@ #ifndef COMBOVIEWER_PANE_INCLUDED #define COMBOVIEWER_PANE_INCLUDED -#include "styleshortcutswitchablepanel.h" #include "sceneviewer.h" #include "toonzqt/intfield.h" #include "toonzqt/keyframenavigator.h" #include "toonzqt/flipconsoleowner.h" +#include "saveloadqsettings.h" + +#include class QPoint; class QToolBar; @@ -30,15 +32,19 @@ class ToolOptions; // ComboViewerPanel //----------------------------------------------------------------------------- enum CV_Parts { - CVPARTS_TOOLBAR = 0, - CVPARTS_TOOLOPTIONS, - CVPARTS_FLIPCONSOLE, - CVPARTS_COUNT + CVPARTS_None = 0, + CVPARTS_TOOLBAR = 0x1, + CVPARTS_TOOLOPTIONS = 0x2, + CVPARTS_FLIPCONSOLE = 0x4, + CVPARTS_End = 0x8, + CVPARTS_ALL = CVPARTS_TOOLBAR | CVPARTS_TOOLOPTIONS | CVPARTS_FLIPCONSOLE }; + //----------------------------------------------------------------------------- -class ComboViewerPanel final : public StyleShortcutSwitchablePanel, - public FlipConsoleOwner { +class ComboViewerPanel final : public QFrame, + public FlipConsoleOwner, + public SaveLoadQSettings { Q_OBJECT SceneViewer *m_sceneViewer; @@ -50,7 +56,7 @@ class ComboViewerPanel final : public StyleShortcutSwitchablePanel, ToolOptions *m_toolOptions; Ruler *m_vRuler; Ruler *m_hRuler; - bool m_visibleFlag[CVPARTS_COUNT]; + UINT m_visiblePartsFlag; bool m_onionSkinActive = false; bool m_playSound = true; bool m_hasSoundtrack = false; @@ -73,37 +79,36 @@ public: ~ComboViewerPanel(); SceneViewer *getSceneViewer() { return m_sceneViewer; } + ToolOptions *getToolOptions() { return m_toolOptions; } - // toggle show/hide of the widgets according to m_visibleFlag + // toggle show/hide of the widgets according to m_visiblePartsFlag + void setVisiblePartsFlag(UINT flag); void updateShowHide(); void addShowHideContextMenu(QMenu *); - void setShowHideFlag(CV_Parts parts, bool visible) { - m_visibleFlag[parts] = visible; - } - bool getShowHideFlag(CV_Parts parts) { return m_visibleFlag[parts]; } - // reimplementation of TPanel::widgetInThisPanelIsFocused - bool widgetInThisPanelIsFocused() override { - return m_sceneViewer->hasFocus(); - } void onDrawFrame(int frame, const ImagePainter::VisualSettings &settings) override; + void onEnterPanel() { + m_sceneViewer->setFocus(Qt::OtherFocusReason); + // activate shortcut key for this flipconsole + m_flipConsole->makeCurrent(); + } + void onLeavePanel() { m_sceneViewer->clearFocus(); } + + // SaveLoadQSettings + virtual void save(QSettings &settings) const override; + virtual void load(QSettings &settings) override; + + void initializeTitleBar(TPanelTitleBar *titleBar); + protected: void showEvent(QShowEvent *) override; void hideEvent(QHideEvent *) override; - void initializeTitleBar(TPanelTitleBar *titleBar); void createFrameToolBar(); void createPlayToolBar(); void addColorMaskButton(QWidget *parent, const char *iconSVGName, int id); void contextMenuEvent(QContextMenuEvent *event) override; - // reimplementation of TPanel::widgetFocusOnEnter - void widgetFocusOnEnter() override { - m_sceneViewer->setFocus(Qt::OtherFocusReason); - // activate shortcut key for this flipconsole - m_flipConsole->makeCurrent(); - }; - void widgetClearFocusOnLeave() override { m_sceneViewer->clearFocus(); }; void playAudioFrame(int frame); bool hasSoundtrack(); @@ -127,8 +132,6 @@ protected slots: void onSceneSwitched(); void enableFullPreview(bool enabled); void enableSubCameraPreview(bool enabled); - - void onPreferenceChanged(const QString &prefName) override; }; #endif diff --git a/toonz/sources/toonz/filebrowser.cpp b/toonz/sources/toonz/filebrowser.cpp index 4d2c576..a9ca57c 100644 --- a/toonz/sources/toonz/filebrowser.cpp +++ b/toonz/sources/toonz/filebrowser.cpp @@ -18,7 +18,6 @@ #include "toonzqt/dvdialog.h" #include "toonzqt/icongenerator.h" #include "toonzqt/menubarcommand.h" -#include "toonzqt/dvdialog.h" #include "toonzqt/gutil.h" #include "toonzqt/trepetitionguard.h" @@ -1200,6 +1199,8 @@ QMenu *FileBrowser::getContextMenu(QWidget *parent, int index) { // iwsw commented out temporarily // menu->addAction(cm->getAction(MI_ToonShadedImageToTLV)); } + if (areFullcolor) menu->addAction(cm->getAction(MI_SeparateColors)); + if (!areFullcolor) menu->addSeparator(); } if (files.size() == 1 && files[0].getType() != "tnz") { diff --git a/toonz/sources/toonz/filebrowsermodel.cpp b/toonz/sources/toonz/filebrowsermodel.cpp index b739367..65012de 100644 --- a/toonz/sources/toonz/filebrowsermodel.cpp +++ b/toonz/sources/toonz/filebrowsermodel.cpp @@ -15,7 +15,6 @@ #include "tapp.h" #include "toonz/tscenehandle.h" -#include "toonz/toonzscene.h" #include #include @@ -1061,16 +1060,19 @@ void DvDirModelRootNode::refreshChildren() { child = new DvDirModelSpecialFileFolderNode(this, L"My Documents", getMyDocumentsPath()); child->setPixmap(svgToPixmap(":Resources/my_documents.svg")); + m_specialNodes.push_back(child); addChild(child); child = new DvDirModelSpecialFileFolderNode(this, L"Desktop", getDesktopPath()); child->setPixmap(svgToPixmap(":Resources/desktop.svg")); + m_specialNodes.push_back(child); addChild(child); child = new DvDirModelSpecialFileFolderNode( this, L"Library", ToonzFolder::getLibraryFolder()); child->setPixmap(svgToPixmap(":Resources/library.svg")); + m_specialNodes.push_back(child); addChild(child); addChild(new DvDirModelHistoryNode(this)); @@ -1191,6 +1193,12 @@ DvDirModelNode *DvDirModelRootNode::getNodeByPath(const TFilePath &path) { if (node) return node; } + // check for the special folders (My Documents / Desktop / Library) + for (DvDirModelSpecialFileFolderNode *specialNode : m_specialNodes) { + DvDirModelNode *node = specialNode->getNodeByPath(path); + if (node) return node; + } + // it could be a regular folder, somewhere in the file system if (m_myComputerNode) { for (i = 0; i < m_myComputerNode->getChildCount(); i++) { diff --git a/toonz/sources/toonz/filebrowsermodel.h b/toonz/sources/toonz/filebrowsermodel.h index 31a4bdf..5680591 100644 --- a/toonz/sources/toonz/filebrowsermodel.h +++ b/toonz/sources/toonz/filebrowsermodel.h @@ -311,6 +311,7 @@ class DvDirModelRootNode final : public DvDirModelNode { DvDirModelNetworkNode *m_networkNode; DvDirModelProjectNode *m_sandboxProjectNode; DvDirModelSceneFolderNode *m_sceneFolderNode; + std::vector m_specialNodes; void add(std::wstring name, const TFilePath &path); diff --git a/toonz/sources/toonz/filebrowserpopup.h b/toonz/sources/toonz/filebrowserpopup.h index 291ea79..a74d202 100644 --- a/toonz/sources/toonz/filebrowserpopup.h +++ b/toonz/sources/toonz/filebrowserpopup.h @@ -156,7 +156,7 @@ public: //! The GenericLoadFilePopup is a simple, standard Toonz popup that //! asks the user for \a single file to be loaded from disk. -class GenericLoadFilePopup final : public FileBrowserPopup { +class GenericLoadFilePopup : public FileBrowserPopup { public: GenericLoadFilePopup(const QString &title); @@ -175,7 +175,7 @@ protected: //! The GenericSaveFilePopup is a simple, standard Toonz popup that //! asks the user for a \a single file path to save something to. -class GenericSaveFilePopup final : public FileBrowserPopup { +class GenericSaveFilePopup : public FileBrowserPopup { public: GenericSaveFilePopup(const QString &title); diff --git a/toonz/sources/toonz/fileselection.cpp b/toonz/sources/toonz/fileselection.cpp index c696e0c..e6a0563 100644 --- a/toonz/sources/toonz/fileselection.cpp +++ b/toonz/sources/toonz/fileselection.cpp @@ -11,6 +11,7 @@ #include "flipbook.h" #include "filebrowsermodel.h" #include "exportscenepopup.h" +#include "separatecolorspopup.h" #include "tapp.h" #include "batches.h" @@ -225,6 +226,7 @@ void FileSelection::enableCommands() { enableCommand(this, MI_ImportScenes, &FileSelection::importScenes); enableCommand(this, MI_ExportScenes, &FileSelection::exportScenes); enableCommand(this, MI_SelectAll, &FileSelection::selectAll); + enableCommand(this, MI_SeparateColors, &FileSelection::separateFilesByColors); } //------------------------------------------------------------------------ @@ -487,6 +489,25 @@ void FileSelection::collectAssets() { //------------------------------------------------------------------------ +void FileSelection::separateFilesByColors() { + std::vector files; + getSelectedFiles(files); + if (files.empty()) return; + + static SeparateColorsPopup *popup = new SeparateColorsPopup(); + if (popup->isConverting()) { + DVGui::MsgBox(INFORMATION, QObject::tr("A separation task is in progress! " + "wait until it stops or cancel it")); + return; + } + popup->setFiles(files); + popup->show(); + popup->raise(); + // popup->exec(); +} + +//------------------------------------------------------------------------ + static int importScene(TFilePath scenePath) { // bool dirtyFlag = TNotifier::instance()->getDirtyFlag(); ToonzScene scene; diff --git a/toonz/sources/toonz/fileselection.h b/toonz/sources/toonz/fileselection.h index d5a90b8..f3c76f8 100644 --- a/toonz/sources/toonz/fileselection.h +++ b/toonz/sources/toonz/fileselection.h @@ -44,6 +44,7 @@ public: void importScenes(); void exportScenes(); void selectAll(); + void separateFilesByColors(); }; #endif // FILESELECTION_H diff --git a/toonz/sources/toonz/filmstrip.cpp b/toonz/sources/toonz/filmstrip.cpp index 7081364..301b8c5 100644 --- a/toonz/sources/toonz/filmstrip.cpp +++ b/toonz/sources/toonz/filmstrip.cpp @@ -112,7 +112,6 @@ FilmstripFrames::FilmstripFrames(QScrollArea *parent, Qt::WFlags flags) , m_dragSelectionStartIndex(-1) , m_dragSelectionEndIndex(-1) , m_timerId(0) - , m_isGhibli(false) , m_selecting(false) , m_dragDropArmed(false) , m_readOnly(false) { @@ -132,10 +131,7 @@ FilmstripFrames::FilmstripFrames(QScrollArea *parent, Qt::WFlags flags) m_selection->setView(this); setMouseTracking(true); - std::string room = - Preferences::instance()->getCurrentRoomChoice().toStdString(); - m_isGhibli = room == "StudioGhibli"; - m_viewer = NULL; + m_viewer = NULL; } //----------------------------------------------------------------------------- @@ -357,26 +353,33 @@ void FilmstripFrames::showEvent(QShowEvent *) { // cambiamenti al livello TXshLevelHandle *levelHandle = app->getCurrentLevel(); - connect(levelHandle, SIGNAL(xshLevelSwitched(TXshLevel *)), this, - SLOT(onLevelSwitched(TXshLevel *))); - connect(levelHandle, SIGNAL(xshLevelChanged()), this, SLOT(onLevelChanged())); - connect(levelHandle, SIGNAL(xshLevelViewChanged()), this, - SLOT(onLevelChanged())); + bool ret = true; + ret = ret && connect(levelHandle, SIGNAL(xshLevelSwitched(TXshLevel *)), this, + SLOT(onLevelSwitched(TXshLevel *))); + ret = ret && connect(levelHandle, SIGNAL(xshLevelChanged()), this, + SLOT(onLevelChanged())); + ret = ret && connect(levelHandle, SIGNAL(xshLevelViewChanged()), this, + SLOT(onLevelChanged())); // al frame corrente - connect(app->getCurrentFrame(), SIGNAL(frameSwitched()), this, - SLOT(onFrameSwitched())); - connect(app->getCurrentFrame(), SIGNAL(frameTypeChanged()), this, - SLOT(update())); + ret = ret && connect(app->getCurrentFrame(), SIGNAL(frameSwitched()), this, + SLOT(onFrameSwitched())); + ret = ret && connect(app->getCurrentFrame(), SIGNAL(frameTypeChanged()), this, + SLOT(update())); // iconcine - connect(IconGenerator::instance(), SIGNAL(iconGenerated()), this, - SLOT(update())); + ret = ret && connect(IconGenerator::instance(), SIGNAL(iconGenerated()), this, + SLOT(update())); // onion skin - connect(app->getCurrentOnionSkin(), SIGNAL(onionSkinMaskChanged()), this, - SLOT(update())); + ret = ret && connect(app->getCurrentOnionSkin(), + SIGNAL(onionSkinMaskChanged()), this, SLOT(update())); + // active viewer change + ret = ret && + connect(app, SIGNAL(activeViewerChanged()), this, SLOT(getViewer())); + + assert(ret); getViewer(); } @@ -402,9 +405,13 @@ void FilmstripFrames::hideEvent(QHideEvent *) { disconnect(app->getCurrentOnionSkin(), SIGNAL(onionSkinMaskChanged()), this, SLOT(update())); + // active viewer change + disconnect(app, SIGNAL(activeViewerChanged()), this, SLOT(getViewer())); + if (m_viewer) { disconnect(m_viewer, SIGNAL(onZoomChanged()), this, SLOT(update())); disconnect(m_viewer, SIGNAL(refreshNavi()), this, SLOT(update())); + m_viewer = nullptr; } } @@ -419,16 +426,13 @@ void FilmstripFrames::getViewer() { } viewerChanged = true; } - ComboViewerPanel *inknPaintViewerPanel = - TApp::instance()->getInknPaintViewerPanel(); - if (m_isGhibli && inknPaintViewerPanel) { - m_viewer = inknPaintViewerPanel->getSceneViewer(); - } else { - m_viewer = TApp::instance()->getActiveViewer(); - } + + m_viewer = TApp::instance()->getActiveViewer(); + if (m_viewer && viewerChanged) { connect(m_viewer, SIGNAL(onZoomChanged()), this, SLOT(update())); connect(m_viewer, SIGNAL(refreshNavi()), this, SLOT(update())); + update(); } } @@ -738,7 +742,7 @@ void FilmstripFrames::mousePressEvent(QMouseEvent *event) { if (fid.getNumber() >= 0 && fid == getCurrentFrameId() && (sl->getType() == TZP_XSHLEVEL || sl->getType() == OVL_XSHLEVEL) && m_viewer && m_viewer->isVisible() && actualIconClicked && - (m_isGhibli != (event->button() == Qt::MiddleButton))) { + event->button() == Qt::MiddleButton) { m_isNavigatorPanning = true; execNavigatorPan(event->pos()); QApplication::setOverrideCursor(Qt::ClosedHandCursor); diff --git a/toonz/sources/toonz/filmstrip.h b/toonz/sources/toonz/filmstrip.h index 469e12e..e72d5a4 100644 --- a/toonz/sources/toonz/filmstrip.h +++ b/toonz/sources/toonz/filmstrip.h @@ -131,7 +131,6 @@ protected: void stopAutoPanning(); void timerEvent(QTimerEvent *) override; TFrameId getCurrentFrameId(); - void getViewer(); void contextMenuEvent(QContextMenuEvent *event) override; void startDragDrop(); @@ -145,6 +144,7 @@ protected slots: void onLevelChanged(); void onLevelSwitched(TXshLevel *); void onFrameSwitched(); + void getViewer(); private: // QSS Properties @@ -166,7 +166,6 @@ private: FilmstripFrameHeadGadget *m_frameHeadGadget; InbetweenDialog *m_inbetweenDialog; SceneViewer *m_viewer; - bool m_isGhibli = false; bool m_justStartedSelection = false; int m_indexForResetSelection = -1; bool m_allowResetSelection = false; diff --git a/toonz/sources/toonz/filmstripcommand.cpp b/toonz/sources/toonz/filmstripcommand.cpp index c2914ec..1dfc524 100644 --- a/toonz/sources/toonz/filmstripcommand.cpp +++ b/toonz/sources/toonz/filmstripcommand.cpp @@ -1819,7 +1819,7 @@ void performReverse(const TXshSimpleLevelP &sl, while (i < j && frames.count(fids[i]) == 0) i++; while (i < j && frames.count(fids[j]) == 0) j--; if (i >= j) break; - tswap(fids[i], fids[j]); + std::swap(fids[i], fids[j]); i++; j--; } diff --git a/toonz/sources/toonz/flipbook.cpp b/toonz/sources/toonz/flipbook.cpp index 8c236bc..ad55025 100644 --- a/toonz/sources/toonz/flipbook.cpp +++ b/toonz/sources/toonz/flipbook.cpp @@ -65,7 +65,6 @@ // Other widgets #include "toonzqt/flipconsole.h" #include "toonzqt/dvdialog.h" -#include "toonzqt/gutil.h" #include "filmstripselection.h" #include "castselection.h" #include "histogrampopup.h" @@ -75,7 +74,6 @@ #include #include #include -#include #include #include #include @@ -90,7 +88,6 @@ #include #include #include -#include #include // for uintptr_t diff --git a/toonz/sources/toonz/frameheadgadget.cpp b/toonz/sources/toonz/frameheadgadget.cpp index 87d90e5..c3dedd0 100644 --- a/toonz/sources/toonz/frameheadgadget.cpp +++ b/toonz/sources/toonz/frameheadgadget.cpp @@ -54,8 +54,10 @@ FrameHeadGadget::~FrameHeadGadget() {} void FrameHeadGadget::draw(QPainter &p, const QColor &lightColor, const QColor &darkColor) { // drawPlayingHead(p, lightColor, darkColor); - if (!Preferences::instance()->isOnionSkinEnabled()) return; - drawOnionSkinSelection(p, lightColor, darkColor); + if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked()) + drawShiftTraceMarker(p); + else if (Preferences::instance()->isOnionSkinEnabled()) + drawOnionSkinSelection(p, lightColor, darkColor); } void FrameHeadGadget::drawPlayingHead(QPainter &p, const QColor &lightColor, @@ -294,7 +296,8 @@ void FrameHeadGadget::setMos(int frame, bool on) { FilmstripFrameHeadGadget::FilmstripFrameHeadGadget(FilmstripFrames *filmstrip) : m_filmstrip(filmstrip) , m_dy(m_filmstrip->getIconSize().height() + fs_frameSpacing + - fs_iconMarginTop + fs_iconMarginBottom) {} + fs_iconMarginTop + fs_iconMarginBottom) + , m_highlightedghostFrame(-1) {} int FilmstripFrameHeadGadget::getY() const { return 50; } @@ -442,7 +445,83 @@ void FilmstripFrameHeadGadget::drawOnionSkinSelection(QPainter &p, //----------------------------------------------------------------------------- +void FilmstripFrameHeadGadget::drawShiftTraceMarker(QPainter &p) { + int currentRow = getCurrentFrame(); + + TPixel frontPixel, backPixel; + bool inksOnly; + Preferences::instance()->getOnionData(frontPixel, backPixel, inksOnly); + QColor frontColor((int)frontPixel.r, (int)frontPixel.g, (int)frontPixel.b); + QColor backColor((int)backPixel.r, (int)backPixel.g, (int)backPixel.b); + + OnionSkinMask osMask = + TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask(); + + // draw lines to ghost frames + int prevOffset = osMask.getShiftTraceGhostFrameOffset(0); + int forwardOffset = osMask.getShiftTraceGhostFrameOffset(1); + + const int shiftTraceDotSize = 12; + const int shiftTraceDotXOffset = 3; + int dotYPos = (m_dy - shiftTraceDotSize) / 2; + + if (currentRow > 0 && prevOffset < 0) // previous ghost + { + p.setPen(backColor); + int y0 = index2y(currentRow + prevOffset) + dotYPos + shiftTraceDotSize; + int y1 = index2y(currentRow); + p.drawLine(shiftTraceDotXOffset + shiftTraceDotSize / 2, y0, + shiftTraceDotXOffset + shiftTraceDotSize / 2, y1); + } + if (forwardOffset > 0) // forward ghost + { + p.setPen(frontColor); + int y0 = index2y(currentRow + 1); + int y1 = index2y(currentRow + forwardOffset) + dotYPos + shiftTraceDotSize; + p.drawLine(shiftTraceDotXOffset + shiftTraceDotSize / 2, y0, + shiftTraceDotXOffset + shiftTraceDotSize / 2, y1); + } + // draw dots + std::vector offsVec = {prevOffset, 0, forwardOffset}; + std::vector colorsVec = {backColor, QColor(0, 162, 232), frontColor}; + QFont currentFont = p.font(); + QFont tmpFont = p.font(); + tmpFont.setPointSize(7); + p.setFont(tmpFont); + + for (int i = 0; i < 3; i++) { + if (i != 1 && offsVec[i] == 0) continue; + p.setPen(colorsVec[i]); + p.setBrush(Qt::gray); + int topPos = index2y(currentRow + offsVec[i]) + dotYPos; + QRect dotRect(shiftTraceDotXOffset, topPos, shiftTraceDotSize, + shiftTraceDotSize); + p.drawRect(dotRect); + + // draw shortcut numbers + p.setPen(Qt::black); + p.drawText(dotRect, Qt::AlignCenter, QString::number(i + 1)); + } + p.setFont(currentFont); + + // highlight on mouse over + if (m_highlightedghostFrame >= 0) { + p.setPen(QColor(255, 255, 0)); + p.setBrush(QColor(255, 255, 0, 180)); + int topPos = index2y(m_highlightedghostFrame) + dotYPos; + QRect dotRect(shiftTraceDotXOffset, topPos, shiftTraceDotSize, + shiftTraceDotSize); + p.drawRect(dotRect); + } +} + +//----------------------------------------------------------------------------- + bool FilmstripFrameHeadGadget::eventFilter(QObject *obj, QEvent *e) { + // shift & trace case + if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked()) + return shiftTraceEventFilter(obj, e); + if (!Preferences::instance()->isOnionSkinEnabled()) return false; QWidget *viewer = dynamic_cast(obj); @@ -650,6 +729,97 @@ bool FilmstripFrameHeadGadget::eventFilter(QObject *obj, QEvent *e) { //----------------------------------------------------------------------------- +bool FilmstripFrameHeadGadget::shiftTraceEventFilter(QObject *obj, QEvent *e) { + QWidget *viewer = dynamic_cast(obj); + + if (e->type() != QEvent::MouseButtonPress && e->type() != QEvent::MouseMove) + return false; + + const int shiftTraceDotSize = 12; + const int shiftTraceDotXOffset = 3; + int dotYPos = (m_dy - shiftTraceDotSize) / 2; + QRect dotRect(shiftTraceDotXOffset, dotYPos, shiftTraceDotSize, + shiftTraceDotSize); + + // reset highlight + if (m_highlightedghostFrame >= 0) { + m_highlightedghostFrame = -1; + viewer->update(); + } + + QMouseEvent *mouseEvent = dynamic_cast(e); + int frame = y2index(mouseEvent->pos().y()); + // position from top-left of the frame + QPoint mousePos = mouseEvent->pos() + QPoint(0, -index2y(frame)); + int currentFrame = getCurrentFrame(); + + if (mousePos.x() < dotRect.left() || mousePos.x() > dotRect.right()) + return false; + + if (e->type() == QEvent::MouseButtonPress) { + if (frame == currentFrame) { + if (dotRect.contains(mousePos)) + OnioniSkinMaskGUI::resetShiftTraceFrameOffset(); + else + return false; + } else { + OnionSkinMask osMask = + TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask(); + int prevOffset = osMask.getShiftTraceGhostFrameOffset(0); + int forwardOffset = osMask.getShiftTraceGhostFrameOffset(1); + // Hide previous ghost + if (frame == currentFrame + prevOffset) + osMask.setShiftTraceGhostFrameOffset(0, 0); + // Hide forward ghost + else if (frame == currentFrame + forwardOffset) + osMask.setShiftTraceGhostFrameOffset(1, 0); + // Move previous ghost + else if (frame < currentFrame) + osMask.setShiftTraceGhostFrameOffset(0, frame - currentFrame); + // Move forward ghost + else + osMask.setShiftTraceGhostFrameOffset(1, frame - currentFrame); + TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(osMask); + } + TApp::instance()->getCurrentOnionSkin()->notifyOnionSkinMaskChanged(); + return true; + } + //---- + else if (e->type() == QEvent::MouseMove) { + if (frame == currentFrame) { + if (dotRect.contains(mousePos)) { + m_highlightedghostFrame = frame; + viewer->setToolTip( + tr("Click to Reset Shift & Trace Markers to Neighbor Frames\nHold " + "F2 Key on the Viewer to Show This Frame Only")); + } else { + viewer->setToolTip(tr("")); + return false; + } + } else { + m_highlightedghostFrame = frame; + OnionSkinMask osMask = + TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask(); + int prevOffset = osMask.getShiftTraceGhostFrameOffset(0); + int forwardOffset = osMask.getShiftTraceGhostFrameOffset(1); + // Hide ghost + if (frame == currentFrame + prevOffset) + viewer->setToolTip( + tr("Click to Hide This Frame from Shift & Trace\nHold F1 Key on " + "the Viewer to Show This Frame Only")); + else if (frame == currentFrame + forwardOffset) + viewer->setToolTip( + tr("Click to Hide This Frame from Shift & Trace\nHold F3 Key on " + "the Viewer to Show This Frame Only")); + // Move ghost + else + viewer->setToolTip(tr("Click to Move Shift & Trace Marker")); + } + } + return true; +} +//----------------------------------------------------------------------------- + class OnionSkinToggle final : public MenuItemHandler { public: OnionSkinToggle() : MenuItemHandler(MI_OnionSkin) {} diff --git a/toonz/sources/toonz/frameheadgadget.h b/toonz/sources/toonz/frameheadgadget.h index 0255bb2..19fd43e 100644 --- a/toonz/sources/toonz/frameheadgadget.h +++ b/toonz/sources/toonz/frameheadgadget.h @@ -46,6 +46,8 @@ public: virtual void drawOnionSkinSelection(QPainter &p, const QColor &lightColor, const QColor &darkColor); + virtual void drawShiftTraceMarker(QPainter &p) {} + virtual int getY() const = 0; virtual int index2y(int index) const = 0; @@ -70,6 +72,7 @@ public: class FilmstripFrameHeadGadget final : public FrameHeadGadget { FilmstripFrames *m_filmstrip; int m_dy; + int m_highlightedghostFrame; public: FilmstripFrameHeadGadget(FilmstripFrames *filmstrip); @@ -81,10 +84,13 @@ public: void drawOnionSkinSelection(QPainter &p, const QColor &lightColor, const QColor &darkColor) override; + void drawShiftTraceMarker(QPainter &p) override; + void setCurrentFrame(int index) const override; int getCurrentFrame() const override; bool eventFilter(QObject *obj, QEvent *event) override; + bool shiftTraceEventFilter(QObject *obj, QEvent *event); }; #endif diff --git a/toonz/sources/toonz/iocommand.cpp b/toonz/sources/toonz/iocommand.cpp index 02f5608..98cd2be 100644 --- a/toonz/sources/toonz/iocommand.cpp +++ b/toonz/sources/toonz/iocommand.cpp @@ -1179,8 +1179,6 @@ IoCmd::ConvertingPopup::~ConvertingPopup() {} bool IoCmd::saveSceneIfNeeded(QString msg) { TApp *app = TApp::instance(); - bool isLevelOrSceneIsDirty = false; - if (app->getCurrentScene()->getDirtyFlag()) { QString question; question = QObject::tr( @@ -1201,8 +1199,6 @@ bool IoCmd::saveSceneIfNeeded(QString msg) { if (!IoCmd::saveScene()) return false; } else if (ret == 3) { } - - isLevelOrSceneIsDirty = true; } ToonzScene *scene = app->getCurrentScene()->getScene(); @@ -1232,29 +1228,11 @@ bool IoCmd::saveSceneIfNeeded(QString msg) { } else if (ret == 1) { // save non scene files IoCmd::saveNonSceneFiles(); - return false; } else if (ret == 2) { - // quit + // do nothing and continue } - - isLevelOrSceneIsDirty = true; } - //--- If both the level and scene is clean, then open the quit confirmation - // dialog - // if (!isLevelOrSceneIsDirty && msg == "Quit") { - // QString question("Are you sure ?"); - // int ret = - // DVGui::MsgBox(question, QObject::tr("OK"), QObject::tr("Cancel"), - // 0); - // if (ret == 0 || ret == 2) { - // // cancel (or closed message box window) - // return false; - // } else if (ret == 1) { - // // ok - // } - //} - RenderingSuspender suspender; TFilePath scenePath(scene->getScenePath()); @@ -2455,10 +2433,6 @@ int IoCmd::loadResources(LoadResourceArguments &args, bool updateRecentFile, // increment the number of loaded resources ++loadedCount; - // move the current column to right - col0++; - app->getCurrentColumn()->setColumnIndex(col0); - // load the image data of all frames to cache at the beginning if (cachingBehavior != ON_DEMAND) { TXshSimpleLevel *simpleLevel = xl->getSimpleLevel(); @@ -2471,6 +2445,8 @@ int IoCmd::loadResources(LoadResourceArguments &args, bool updateRecentFile, } } + if (loadedCount) app->getCurrentFrame()->setFrameIndex(row0); + sb->data().m_loadedCount += loadedCount; sb->data().m_hasSoundLevel = sb->data().m_hasSoundLevel || isSoundLevel; diff --git a/toonz/sources/toonz/keyframedata.cpp b/toonz/sources/toonz/keyframedata.cpp index 73f6bae..b09f02c 100644 --- a/toonz/sources/toonz/keyframedata.cpp +++ b/toonz/sources/toonz/keyframedata.cpp @@ -23,7 +23,8 @@ TKeyframeData::TKeyframeData() {} TKeyframeData::TKeyframeData(const TKeyframeData *src) : m_keyData(src->m_keyData) - , m_isPegbarsCycleEnabled(src->m_isPegbarsCycleEnabled) {} + , m_isPegbarsCycleEnabled(src->m_isPegbarsCycleEnabled) + , m_offset(src->m_offset) {} //----------------------------------------------------------------------------- @@ -32,6 +33,12 @@ TKeyframeData::~TKeyframeData() {} //----------------------------------------------------------------------------- // data <- xsheet void TKeyframeData::setKeyframes(std::set positions, TXsheet *xsh) { + Position startPos(-1, -1); + setKeyframes(positions, xsh, startPos); +} + +void TKeyframeData::setKeyframes(std::set positions, TXsheet *xsh, + Position startPos) { if (positions.empty()) return; TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); @@ -51,6 +58,9 @@ void TKeyframeData::setKeyframes(std::set positions, TXsheet *xsh) { m_columnSpanCount = c1 - c0 + 1; m_rowSpanCount = r1 - r0 + 1; + if (startPos.first >= 0 && startPos.second >= 0) + m_offset = std::make_pair(r0 - startPos.first, c0 - startPos.second); + for (it = positions.begin(); it != positions.end(); ++it) { int row = it->first; int col = it->second; @@ -126,3 +136,7 @@ void TKeyframeData::getKeyframes(std::set &positions) const { TKeyframeSelection::Position(pos.first + r0, pos.second + c0)); } } + +void TKeyframeData::setKeyframesOffset(int row, int col) { + m_offset = std::make_pair(row, col); +} diff --git a/toonz/sources/toonz/keyframedata.h b/toonz/sources/toonz/keyframedata.h index 3f9aada..eb86df9 100644 --- a/toonz/sources/toonz/keyframedata.h +++ b/toonz/sources/toonz/keyframedata.h @@ -25,6 +25,8 @@ public: int m_columnSpanCount; int m_rowSpanCount; + Position m_offset = std::make_pair(0, 0); + // Numero di colonna della pegbar associato al booleano isCycleEnabled della // pegbar std::map m_isPegbarsCycleEnabled; @@ -37,6 +39,8 @@ public: // data <- xsh void setKeyframes(std::set positions, TXsheet *xsh); + void setKeyframes(std::set positions, TXsheet *xsh, + Position startPos); // data -> xsh bool getKeyframes(std::set &positions, TXsheet *xsh) const; @@ -52,6 +56,9 @@ public: int getColumnSpanCount() const { return m_columnSpanCount; } int getRowSpanCount() const { return m_rowSpanCount; } + + void setKeyframesOffset(int row, int col); + Position getKeyframesOffset() const { return m_offset; } }; #endif // KEYFRAMEDATA_INCLUDED diff --git a/toonz/sources/toonz/keyframemover.cpp b/toonz/sources/toonz/keyframemover.cpp index 37b66a0..39d1c39 100644 --- a/toonz/sources/toonz/keyframemover.cpp +++ b/toonz/sources/toonz/keyframemover.cpp @@ -346,8 +346,8 @@ void KeyframeMoverTool::rectSelect(int row, int col) { selection->selectNone(); TXsheet *xsh = getViewer()->getXsheet(); int r0 = row, c0 = col, r1 = m_firstRow, c1 = m_firstCol; - if (r0 > r1) tswap(r0, r1); - if (c0 > c1) tswap(c0, c1); + if (r0 > r1) std::swap(r0, r1); + if (c0 > c1) std::swap(c0, c1); for (int c = c0; c <= c1; c++) { TStageObject *obj = xsh->getStageObject(getViewer()->getObjectId(c)); for (int r = r0; r <= r1; r++) { diff --git a/toonz/sources/toonz/keyframeselection.cpp b/toonz/sources/toonz/keyframeselection.cpp index 526a326..385c7f5 100644 --- a/toonz/sources/toonz/keyframeselection.cpp +++ b/toonz/sources/toonz/keyframeselection.cpp @@ -144,12 +144,17 @@ public: // data->xsh void setXshFromData(QMimeData *data) const { const TKeyframeData *keyframeData = dynamic_cast(data); - if (keyframeData) - pasteKeyframesWithoutUndo(keyframeData, &m_selection->getSelection()); + if (keyframeData) { + TKeyframeSelection *selection = + new TKeyframeSelection(m_selection->getSelection()); + pasteKeyframesWithoutUndo(keyframeData, &selection->getSelection()); + } } void undo() const override { // Delete merged data - deleteKeyframesWithoutUndo(&m_selection->getSelection()); + TKeyframeSelection *selection = + new TKeyframeSelection(m_selection->getSelection()); + deleteKeyframesWithoutUndo(&selection->getSelection()); if (-(m_r1 - m_r0 + 1) != 0) shiftKeyframesWithoutUndo(m_r0, m_r1, m_c0, m_c1, true); if (m_oldData) setXshFromData(m_oldData); diff --git a/toonz/sources/toonz/kis_tablet_support_win8.cpp b/toonz/sources/toonz/kis_tablet_support_win8.cpp new file mode 100644 index 0000000..c196885 --- /dev/null +++ b/toonz/sources/toonz/kis_tablet_support_win8.cpp @@ -0,0 +1,1232 @@ +/* +* This file is based on the Windows Pointer Input Message support code files by +* Alvin Wong. +* Notwithstanding the license specified in this repository, this file is +* redistributed under BSD 2-Clause license written below in order to keep +* backporting available. +* +* All contributions by Alvin Wong: +* Copyright (c) 2017 Alvin Wong +* All rights reserved. +* +* All other contributions: +* Copyright (c) 2018, the respective contributors. +* All rights reserved. +* +* Each contributor holds copyright over their respective contributions. +* The project versioning (Git) records all such contribution source information. +* +* Redistribution and use in source and binary forms, with or without +- modification, are permitted provided that the following conditions +- are met: +- +- 1. Redistributions of source code must retain the above copyright +- notice, this list of conditions and the following disclaimer. +- 2. Redistributions in binary form must reproduce the above copyright +- notice, this list of conditions and the following disclaimer in the +- documentation and/or other materials provided with the distribution. +- +- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// Get Windows 8 API prototypes and types +#ifdef WINVER +#undef WINVER +#endif +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define WINVER 0x0602 +#define _WIN32_WINNT 0x0602 + +#include "kis_tablet_support_win8.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef _WIN32 + +#ifdef KRITA +#include +#endif + +#include +#include + +#ifndef Q_OS_WIN +#error This file must not be compiled for non-Windows systems +#endif + +namespace { + +class Win8PointerInputApi { +#define WIN8_POINTER_INPUT_API_LIST(FUNC) \ + /* Pointer Input Functions */ \ + FUNC(GetPointerPenInfo) \ + FUNC(GetPointerPenInfoHistory) \ + FUNC(GetPointerType) \ + /* Pointer Device Functions */ \ + FUNC(GetPointerDevices) \ + /*FUNC(GetPointerDeviceProperties)*/ \ + FUNC(GetPointerDevice) \ + FUNC(GetPointerDeviceRects) \ + /*FUNC(RegisterPointerDeviceNotifications)*/ \ + /* end */ + + bool m_loaded; + +public: +#define DEFINE_FP_FROM_WINAPI(func) \ + \ +public: \ + using p##func##_t = std::add_pointer::type; \ + \ +private: \ + p##func##_t m_p##func = nullptr; \ + \ +public: \ + const p##func##_t &func = m_p##func; // const fp ref to member + + WIN8_POINTER_INPUT_API_LIST(DEFINE_FP_FROM_WINAPI) + +#undef DEFINE_FP_FROM_WINAPI + +public: + Win8PointerInputApi() : m_loaded(false) {} + + bool init() { + if (m_loaded) { + return true; + } + + QLibrary user32Lib("user32"); + if (!user32Lib.load()) { + qWarning() << "Failed to load user32.dll! This really should not happen."; + return false; + } + +#ifdef KRITA +#define LOAD_AND_CHECK_FP_FROM_WINAPI(func) \ + m_p##func = reinterpret_cast(user32Lib.resolve(#func)); \ + if (!m_p##func) { \ + dbgTablet << "Failed to load function " #func " from user32.dll"; \ + return false; \ + } +#else +#define LOAD_AND_CHECK_FP_FROM_WINAPI(func) \ + m_p##func = reinterpret_cast(user32Lib.resolve(#func)); \ + if (!m_p##func) { \ + return false; \ + } +#endif + + WIN8_POINTER_INPUT_API_LIST(LOAD_AND_CHECK_FP_FROM_WINAPI) + +#undef LOAD_AND_CHECK_FP_FROM_WINAPI + +#ifdef KRITA + dbgTablet << "Loaded Windows 8 Pointer Input API functions"; +#endif + m_loaded = true; + return true; + } + + bool isLoaded() { return m_loaded; } + +#undef WIN8_POINTER_INPUT_API_LIST +}; // class Win8PointerInputApi + +Win8PointerInputApi api; + +class PointerFlagsWrapper { + const POINTER_FLAGS f; + +public: + PointerFlagsWrapper(POINTER_FLAGS flags) : f(flags) {} + + static PointerFlagsWrapper fromPointerInfo(const POINTER_INFO &pointerInfo) { + return PointerFlagsWrapper(pointerInfo.pointerFlags); + } + + static PointerFlagsWrapper fromPenInfo(const POINTER_PEN_INFO &penInfo) { + return fromPointerInfo(penInfo.pointerInfo); + } + + bool isNew() const { return f & POINTER_FLAG_NEW; } + + bool isInRange() const { return f & POINTER_FLAG_INRANGE; } + + bool isInContact() const { return f & POINTER_FLAG_INCONTACT; } + + bool isFirstButtonDown() const { return f & POINTER_FLAG_FIRSTBUTTON; } + + bool isSecondButtonDown() const { return f & POINTER_FLAG_SECONDBUTTON; } + + bool isThirdButtonDown() const { return f & POINTER_FLAG_THIRDBUTTON; } + + bool isForthButtonDown() const { return f & POINTER_FLAG_FOURTHBUTTON; } + + bool isFifthButtonDown() const { return f & POINTER_FLAG_FIFTHBUTTON; } + + bool isPrimary() const { return f & POINTER_FLAG_PRIMARY; } + + bool isConfidence() const { return f & POINTER_FLAG_CONFIDENCE; } + + bool isCancelled() const { return f & POINTER_FLAG_CANCELED; } + + bool isDown() const { return f & POINTER_FLAG_DOWN; } + + bool isUpdate() const { return f & POINTER_FLAG_UPDATE; } + + bool isUp() const { return f & POINTER_FLAG_UP; } + + bool isWheel() const { return f & POINTER_FLAG_WHEEL; } + + bool isHWheel() const { return f & POINTER_FLAG_HWHEEL; } + + bool isCaptureChanged() const { return f & POINTER_FLAG_CAPTURECHANGED; } + + bool hasTransform() const { + // mingw-w64 headers is missing this flag + // return f & POINTER_FLAG_HASTRANSFORM; + return f & 0x00400000; + } +}; // class PointerFlagsWrapper + +class PenFlagsWrapper { + const PEN_FLAGS f; + +public: + PenFlagsWrapper(PEN_FLAGS flags) : f(flags) {} + + static PenFlagsWrapper fromPenInfo(const POINTER_PEN_INFO &penInfo) { + return PenFlagsWrapper(penInfo.penFlags); + } + + bool isBarrelPressed() const { return f & PEN_FLAG_BARREL; } + + bool isInverted() const { return f & PEN_FLAG_INVERTED; } + + bool isEraserPressed() const { return f & PEN_FLAG_ERASER; } +}; // class PenFlagsWrapper + +class PenMaskWrapper { + const PEN_MASK f; + +public: + PenMaskWrapper(PEN_MASK mask) : f(mask) {} + + static PenMaskWrapper fromPenInfo(const POINTER_PEN_INFO &penInfo) { + return PenMaskWrapper(penInfo.penMask); + } + + bool pressureValid() const { return f & PEN_MASK_PRESSURE; } + + bool rotationValid() const { return f & PEN_MASK_ROTATION; } + + bool tiltXValid() const { return f & PEN_MASK_TILT_X; } + + bool tiltYValid() const { return f & PEN_MASK_TILT_Y; } +}; // class PenMaskWrapper + +struct PointerDeviceItem { + // HANDLE handle; + // RECT pointerDeviceRect; + // RECT displayRect; + qreal himetricToPixelX; + qreal himetricToPixelY; + qreal pixelOffsetX; + qreal pixelOffsetY; + DISPLAYCONFIG_ROTATION deviceOrientation; // This is needed to fix tilt +}; + +QHash penDevices; + +struct PenPointerItem { + // int pointerId; + // POINTER_PEN_INFO penInfo; + HWND hwnd; + HANDLE deviceHandle; + QPointer activeWidget; // Current widget receiving events + qreal oneOverDpr; // 1 / devicePixelRatio of activeWidget + bool widgetIsCaptured; // Current widget is capturing a pen cown event + bool widgetIsIgnored; // Pen events should be ignored until pen up + bool widgetAcceptsPenEvent; // Whether the widget accepts pen events + + bool isCaptured() const { return widgetIsCaptured; } +}; + +QHash penPointers; +// int primaryPenPointerId; + +bool handlePointerMsg(const MSG &msg); + +// extern "C" { +// +// LRESULT CALLBACK pointerDeviceNotificationsWndProc(HWND hwnd, UINT uMsg, +// WPARAM wParam, LPARAM lParam) +// { +// switch (uMsg) { +// case WM_POINTERDEVICECHANGE: +// dbgTablet << "I would want to handle this WM_POINTERDEVICECHANGE +// event, but ms just doesn't want me to use it"; +// dbgTablet << " wParam:" << wParam; +// dbgTablet << " lParam:" << lParam; +// return 0; +// case WM_POINTERDEVICEINRANGE: +// dbgTablet << "I would want to handle this WM_POINTERDEVICEINRANGE +// event, but ms just doesn't want me to use it"; +// dbgTablet << " wParam:" << wParam; +// dbgTablet << " lParam:" << lParam; +// return 0; +// case WM_POINTERDEVICEOUTOFRANGE: +// dbgTablet << "I would want to handle this WM_POINTERDEVICEOUTOFRANGE +// event, but ms just doesn't want me to use it"; +// dbgTablet << " wParam:" << wParam; +// dbgTablet << " lParam:" << lParam; +// return 0; +// } +// return DefWindowProcW(hwnd, uMsg, wParam, lParam); +// } +// +// } // extern "C" + +} // namespace + +bool KisTabletSupportWin8::isAvailable() { + // Just try loading the APIs + return api.init(); +} + +bool KisTabletSupportWin8::isPenDeviceAvailable() { + if (!api.init()) { + return false; + } + UINT32 deviceCount = 0; + if (!api.GetPointerDevices(&deviceCount, nullptr)) { +#ifdef KRITA + dbgTablet << "GetPointerDevices failed"; +#endif + return false; + } + if (deviceCount == 0) { +#ifdef KRITA + dbgTablet << "No pointer devices"; +#endif + return false; + } + QVector devices(deviceCount); + if (!api.GetPointerDevices(&deviceCount, devices.data())) { +#ifdef KRITA + dbgTablet << "GetPointerDevices failed"; +#endif + return false; + } + bool hasPenDevice = false; + Q_FOREACH (const POINTER_DEVICE_INFO &device, devices) { +#ifdef KRITA + dbgTablet << "Found pointer device" << static_cast(device.device) + << QString::fromWCharArray(device.productString) + << "type:" << device.pointerDeviceType; +#endif + if (device.pointerDeviceType == POINTER_DEVICE_TYPE_INTEGRATED_PEN || + device.pointerDeviceType == POINTER_DEVICE_TYPE_EXTERNAL_PEN) { + hasPenDevice = true; + } + } +#ifdef KRITA + dbgTablet << "hasPenDevice:" << hasPenDevice; +#endif + return hasPenDevice; +} + +bool KisTabletSupportWin8::init() { return api.init(); } + +// void KisTabletSupportWin8::registerPointerDeviceNotifications() +// { +// const wchar_t *className = L"w8PointerMsgWindow"; +// HINSTANCE hInst = static_cast(GetModuleHandleW(nullptr)); +// WNDCLASSEXW wc; +// wc.cbSize = sizeof(WNDCLASSEXW); +// wc.style = 0; +// wc.lpfnWndProc = pointerDeviceNotificationsWndProc; +// wc.cbClsExtra = 0; +// wc.cbWndExtra = 0; +// wc.hInstance = hInst; +// wc.hCursor = 0; +// wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW); +// wc.hIcon = 0; +// wc.hIconSm = 0; +// wc.lpszMenuName = 0; +// wc.lpszClassName = className; +// +// if (RegisterClassEx(&wc)) { +// HWND hwnd = CreateWindowEx(0, className, nullptr, 0, 0, 0, 0, 0, +// HWND_MESSAGE, nullptr, hInst, nullptr); +// api.RegisterPointerDeviceNotifications(hwnd, TRUE); +// } else { +// dbgTablet << "Cannot register dummy window"; +// } +// } + +bool KisTabletSupportWin8::nativeEventFilter(const QByteArray &eventType, + void *message, long *result) { + if (!result) { + // I don't know why this even happens, but it actually does + // And the same event is sent in again with result != nullptr + return false; + } + + // This is only installed on Windows so there is no reason to check eventType + MSG &msg = *static_cast(message); + + switch (msg.message) { + case WM_POINTERDOWN: + case WM_POINTERUP: + case WM_POINTERENTER: + case WM_POINTERLEAVE: + case WM_POINTERUPDATE: + case WM_POINTERCAPTURECHANGED: { + bool handled = handlePointerMsg(msg); + if (handled) { + *result = 0; + return true; + } + break; + } + case WM_TABLET_QUERYSYSTEMGESTURESTATUS: + *result = 0; + return true; + } + + Q_UNUSED(eventType) + return false; +} + +namespace { + +QDebug operator<<(QDebug debug, const POINT &pt) { + QDebugStateSaver saver(debug); + debug.nospace() << '(' << pt.x << ", " << pt.y << ')'; + + return debug; +} + +QDebug operator<<(QDebug debug, const RECT &rect) { + QDebugStateSaver saver(debug); + debug.nospace() << '(' << rect.left << ", " << rect.top << ", " << rect.right + << ", " << rect.bottom << ')'; + + return debug; +} + +bool registerOrUpdateDevice(HANDLE deviceHandle, const RECT &pointerDeviceRect, + const RECT &displayRect, + const DISPLAYCONFIG_ROTATION deviceOrientation) { + bool isPreviouslyRegistered = penDevices.contains(deviceHandle); + PointerDeviceItem &deviceItem = penDevices[deviceHandle]; + PointerDeviceItem oldDeviceItem = deviceItem; + // deviceItem.handle = deviceHandle; + deviceItem.himetricToPixelX = + static_cast(displayRect.right - displayRect.left) / + (pointerDeviceRect.right - pointerDeviceRect.left); + deviceItem.himetricToPixelY = + static_cast(displayRect.bottom - displayRect.top) / + (pointerDeviceRect.bottom - pointerDeviceRect.top); + deviceItem.pixelOffsetX = + static_cast(displayRect.left) - + deviceItem.himetricToPixelX * pointerDeviceRect.left; + deviceItem.pixelOffsetY = static_cast(displayRect.top) - + deviceItem.himetricToPixelY * pointerDeviceRect.top; + deviceItem.deviceOrientation = deviceOrientation; + if (!isPreviouslyRegistered) { +#ifdef KRITA + dbgTablet << "Registered pen device" << deviceHandle << "with displayRect" + << displayRect << "and deviceRect" << pointerDeviceRect << "scale" + << deviceItem.himetricToPixelX << deviceItem.himetricToPixelY + << "offset" << deviceItem.pixelOffsetX << deviceItem.pixelOffsetY + << "orientation" << deviceItem.deviceOrientation; +#endif + } else if (deviceItem.himetricToPixelX != oldDeviceItem.himetricToPixelX || + deviceItem.himetricToPixelY != oldDeviceItem.himetricToPixelY || + deviceItem.pixelOffsetX != oldDeviceItem.pixelOffsetX || + deviceItem.pixelOffsetY != oldDeviceItem.pixelOffsetY || + deviceItem.deviceOrientation != oldDeviceItem.deviceOrientation) { +#ifdef KRITA + dbgTablet << "Updated pen device" << deviceHandle << "with displayRect" + << displayRect << "and deviceRect" << pointerDeviceRect << "scale" + << deviceItem.himetricToPixelX << deviceItem.himetricToPixelY + << "offset" << deviceItem.pixelOffsetX << deviceItem.pixelOffsetY + << "orientation" << deviceItem.deviceOrientation; +#endif + } + return true; +} + +bool registerOrUpdateDevice(HANDLE deviceHandle) { + RECT pointerDeviceRect, displayRect; + if (!api.GetPointerDeviceRects(deviceHandle, &pointerDeviceRect, + &displayRect)) { +#ifdef KRITA + dbgTablet << "GetPointerDeviceRects failed"; +#endif + return false; + } + POINTER_DEVICE_INFO pointerDeviceInfo; + if (!api.GetPointerDevice(deviceHandle, &pointerDeviceInfo)) { +#ifdef KRITA + dbgTablet << "GetPointerDevice failed"; +#endif + return false; + } + return registerOrUpdateDevice(deviceHandle, pointerDeviceRect, displayRect, + static_cast( + pointerDeviceInfo.displayOrientation)); +} + +QTabletEvent makeProximityTabletEvent(const QEvent::Type eventType, + const POINTER_PEN_INFO &penInfo) { + PenFlagsWrapper penFlags = PenFlagsWrapper::fromPenInfo(penInfo); + QTabletEvent::PointerType pointerType = + penFlags.isInverted() ? QTabletEvent::Eraser : QTabletEvent::Pen; + const QPointF emptyPoint; + return QTabletEvent( + eventType, // type + emptyPoint, // pos + emptyPoint, // globalPos + QTabletEvent::Stylus, // device + pointerType, // pointerType + 0, // pressure + 0, // xTilt + 0, // yTilt + 0, // tangentialPressure + 0, // rotation + 0, // z + Qt::NoModifier, // keyState + reinterpret_cast(penInfo.pointerInfo.sourceDevice), // uniqueID + Qt::NoButton, // button + (Qt::MouseButtons)0 // buttons + ); +} + +// void rotateTiltAngles(int &tiltX, int &tiltY, const DISPLAYCONFIG_ROTATION +// orientation) { +// int newTiltX, newTiltY; +// switch (orientation) { +// case DISPLAYCONFIG_ROTATION_ROTATE90: +// newTiltX = -tiltY; +// newTiltY = tiltX; +// break; +// case DISPLAYCONFIG_ROTATION_ROTATE180: +// newTiltX = -tiltX; +// newTiltY = -tiltY; +// break; +// case DISPLAYCONFIG_ROTATION_ROTATE270: +// newTiltX = tiltY; +// newTiltY = -tiltX; +// break; +// case DISPLAYCONFIG_ROTATION_IDENTITY: +// default: +// newTiltX = tiltX; +// newTiltY = tiltY; +// break; +// } +// tiltX = newTiltX; +// tiltY = newTiltY; +// } + +QTabletEvent makePositionalTabletEvent(const QWidget *targetWidget, + const QEvent::Type eventType, + const POINTER_PEN_INFO &penInfo, + const PointerDeviceItem &deviceItem, + const PenPointerItem &penPointerItem) { + PenFlagsWrapper penFlags = PenFlagsWrapper::fromPenInfo(penInfo); + PointerFlagsWrapper pointerFlags = PointerFlagsWrapper::fromPenInfo(penInfo); + PenMaskWrapper penMask = PenMaskWrapper::fromPenInfo(penInfo); + + const QPointF globalPosF((deviceItem.himetricToPixelX * + penInfo.pointerInfo.ptHimetricLocationRaw.x + + deviceItem.pixelOffsetX) * + penPointerItem.oneOverDpr, + (deviceItem.himetricToPixelY * + penInfo.pointerInfo.ptHimetricLocationRaw.y + + deviceItem.pixelOffsetY) * + penPointerItem.oneOverDpr); + const QPoint globalPos = globalPosF.toPoint(); + const QPoint localPos = targetWidget->mapFromGlobal(globalPos); + const QPointF delta = globalPosF - globalPos; + const QPointF localPosF = localPos + delta; + + const QTabletEvent::PointerType pointerType = + penFlags.isInverted() ? QTabletEvent::Eraser : QTabletEvent::Pen; + + Qt::MouseButton mouseButton; + if (eventType == QEvent::TabletPress) { + if (penInfo.pointerInfo.ButtonChangeType == + POINTER_CHANGE_SECONDBUTTON_DOWN) { + mouseButton = Qt::RightButton; + } else { +#ifdef KRITA + KIS_SAFE_ASSERT_RECOVER(penInfo.pointerInfo.ButtonChangeType == + POINTER_CHANGE_FIRSTBUTTON_DOWN) { +#else + if (!(penInfo.pointerInfo.ButtonChangeType == + POINTER_CHANGE_FIRSTBUTTON_DOWN)) { +#endif + qWarning() << "WM_POINTER* sent unknown ButtonChangeType" + << penInfo.pointerInfo.ButtonChangeType; + } + mouseButton = Qt::LeftButton; + } + } else if (eventType == QEvent::TabletRelease) { + if (penInfo.pointerInfo.ButtonChangeType == + POINTER_CHANGE_SECONDBUTTON_UP) { + mouseButton = Qt::RightButton; + } else { +#ifdef KRITA + KIS_SAFE_ASSERT_RECOVER(penInfo.pointerInfo.ButtonChangeType == + POINTER_CHANGE_FIRSTBUTTON_UP) { +#else + if (!(penInfo.pointerInfo.ButtonChangeType == + POINTER_CHANGE_FIRSTBUTTON_UP)) { +#endif + qWarning() << "WM_POINTER* sent unknown ButtonChangeType" + << penInfo.pointerInfo.ButtonChangeType; + } + mouseButton = Qt::LeftButton; + } + } else { + mouseButton = Qt::NoButton; + } + + Qt::MouseButtons mouseButtons; + if (pointerFlags.isFirstButtonDown()) { + mouseButtons |= Qt::LeftButton; + } + if (pointerFlags.isSecondButtonDown()) { + mouseButtons |= Qt::RightButton; + } + + int tiltX = 0, tiltY = 0; + if (penMask.tiltXValid()) { + tiltX = qBound(-60, penInfo.tiltX, 60); + } + if (penMask.tiltYValid()) { + tiltY = qBound(-60, penInfo.tiltY, 60); + } + // rotateTiltAngles(tiltX, tiltY, deviceItem.deviceOrientation); + + int rotation = 0; + if (penMask.rotationValid()) { + rotation = + 360 - penInfo.rotation; // Flip direction and convert to signed int + if (rotation > 180) { + rotation -= 360; + } + } + + return QTabletEvent( + eventType, // type + localPosF, // pos + globalPosF, // globalPos + QTabletEvent::Stylus, // device + pointerType, // pointerType + penMask.pressureValid() ? static_cast(penInfo.pressure) / 1024 + : 0, // pressure + tiltX, // xTilt + tiltY, // yTilt + 0, // tangentialPressure + rotation, // rotation + 0, // z + QApplication::queryKeyboardModifiers(), // keyState + reinterpret_cast(penInfo.pointerInfo.sourceDevice), // uniqueID + mouseButton, // button + mouseButtons // buttons + ); +} + +bool sendProximityTabletEvent(const QEvent::Type eventType, + const POINTER_PEN_INFO &penInfo) { +#ifdef KRITA + KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE( + eventType == QEvent::TabletEnterProximity || + eventType == QEvent::TabletLeaveProximity, + false); +#else + if (!(eventType == QEvent::TabletEnterProximity || + eventType == QEvent::TabletLeaveProximity)) { + return false; + } +#endif + QTabletEvent ev = makeProximityTabletEvent(eventType, penInfo); + ev.setAccepted(false); + ev.setTimestamp(penInfo.pointerInfo.dwTime); + QCoreApplication::sendEvent(qApp, &ev); + return ev.isAccepted(); +} + +void synthesizeMouseEvent(const QTabletEvent &ev, + const POINTER_PEN_INFO &penInfo) { + // Update the cursor position + BOOL result = SetCursorPos(penInfo.pointerInfo.ptPixelLocationRaw.x, + penInfo.pointerInfo.ptPixelLocationRaw.y); + if (!result) { +#ifdef KRITA + dbgInput << "SetCursorPos failed, err" << GetLastError(); +#endif + return; + } + // Send mousebutton down/up events. Windows stores the button state. + DWORD inputDataFlags = 0; + switch (ev.type()) { + case QEvent::TabletPress: + switch (ev.button()) { + case Qt::LeftButton: + inputDataFlags = MOUSEEVENTF_LEFTDOWN; + break; + case Qt::RightButton: + inputDataFlags = MOUSEEVENTF_RIGHTDOWN; + break; + default: + return; + } + break; + case QEvent::TabletRelease: + switch (ev.button()) { + case Qt::LeftButton: + inputDataFlags = MOUSEEVENTF_LEFTUP; + break; + case Qt::RightButton: + inputDataFlags = MOUSEEVENTF_RIGHTUP; + break; + default: + return; + } + break; + case QEvent::TabletMove: + default: + return; + } + INPUT inputData = {}; + inputData.type = INPUT_MOUSE; + inputData.mi.dwFlags = inputDataFlags; + inputData.mi.dwExtraInfo = + 0xFF515700 | + 0x01; // https://msdn.microsoft.com/en-us/library/windows/desktop/ms703320%28v=vs.85%29.aspx + UINT result2 = SendInput(1, &inputData, sizeof(inputData)); + if (result2 != 1) { +#ifdef KRITA + dbgInput << "SendInput failed, err" << GetLastError(); +#endif + return; + } +} + +bool sendPositionalTabletEvent(QWidget *target, const QEvent::Type eventType, + const POINTER_PEN_INFO &penInfo, + const PointerDeviceItem &device, + const PenPointerItem &penPointerItem, + const bool shouldSynthesizeMouseEvent) { +#ifdef KRITA + KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(eventType == QEvent::TabletMove || + eventType == QEvent::TabletPress || + eventType == QEvent::TabletRelease, + false); +#else + if (!(eventType == QEvent::TabletMove || eventType == QEvent::TabletPress || + eventType == QEvent::TabletRelease)) { + return false; + } +#endif + QTabletEvent ev = makePositionalTabletEvent(target, eventType, penInfo, + device, penPointerItem); + ev.setAccepted(false); + ev.setTimestamp(penInfo.pointerInfo.dwTime); + QCoreApplication::sendEvent(target, &ev); + if (!shouldSynthesizeMouseEvent) { + // For pen update with multiple updates, only the last update should + // be used to synthesize a mouse event. + return false; + } + // This is some specialized code to handle synthesizing of mouse events from + // the pen events. Issues being: + // 1. We must accept the pointer down/up and the intermediate update events + // to indicate that we want all the pen pointer events for painting, + // otherwise Windows may do weird stuff and skip passing pointer events. + // 2. Some Qt and Krita code uses QCursor::pos() which calls GetCursorPos to + // get the cursor position. This doesn't work nicely before ver 1709 and + // doesn't work at all on ver 1709 if the pen events are handled, so we + // need some way to nudge the cursor on the OS level. + // It appears that using the same way (as in synthesizeMouseEvent) to nudge + // the cursor does work fine for when painting on canvas (which handles + // the QTabletEvent), but not for other widgets because it introduces a lag + // with mouse move events on move start and immediately after mouse down. + // The resolution is to simulate mouse movement with our own code only for + // handled pen events, which is what the following code does. + if (ev.type() == QEvent::TabletMove && ev.buttons() == Qt::NoButton) { + // Let Windows synthesize mouse hover events + return false; + } + if (ev.type() == QEvent::TabletPress && !ev.isAccepted()) { + // On pen down event, if the widget doesn't handle the event, let + // Windows translate the event to touch, mouse or whatever + return false; + } + if (ev.type() != QEvent::TabletPress && + !penPointerItem.widgetAcceptsPenEvent) { + // For other events, if the previous pen down event wasn't handled by + // the widget, continue to let Windows translate the event + return false; + } + // Otherwise, we synthesize our mouse events + synthesizeMouseEvent(ev, penInfo); + return true; // and tell Windows that we do want the pen events. +} + +bool handlePenEnterMsg(const POINTER_PEN_INFO &penInfo) { + PointerFlagsWrapper pointerFlags = PointerFlagsWrapper::fromPenInfo(penInfo); + if (!pointerFlags.isPrimary()) { +// Don't handle non-primary pointer messages for now +#ifdef KRITA + dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId << "of device" + << penInfo.pointerInfo.sourceDevice << "is not flagged PRIMARY"; +#endif + return false; + } + + // Update the device scaling factors here + // It doesn't cost much to recalculate anyway + // This ensures that the screen resolution changes are reflected + // WM_POINTERDEVICECHANGE might be useful for this, but its docs are too + // unclear to use + registerOrUpdateDevice(penInfo.pointerInfo.sourceDevice); + // TODO: Need a way to remove from device registration when devices are + // changed + + // We now only handle one pointer at a time, so just clear the pointer + // registration + penPointers.clear(); + + int pointerId = penInfo.pointerInfo.pointerId; + PenPointerItem penPointerItem; + penPointerItem.hwnd = penInfo.pointerInfo.hwndTarget; + penPointerItem.deviceHandle = penInfo.pointerInfo.sourceDevice; + penPointerItem.activeWidget = nullptr; + penPointerItem.oneOverDpr = 1.0; + penPointerItem.widgetIsCaptured = false; + penPointerItem.widgetIsIgnored = false; + penPointerItem.widgetAcceptsPenEvent = false; + // penPointerItem.pointerId = pointerId; + + penPointers.insert(pointerId, penPointerItem); + // primaryPenPointerId = pointerId; + + // penEnter + sendProximityTabletEvent(QEvent::TabletEnterProximity, penInfo); + + return false; +} + +bool handlePenLeaveMsg(const POINTER_PEN_INFO &penInfo) { + if (!penPointers.contains(penInfo.pointerInfo.pointerId)) { +#ifdef KRITA + dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId + << "wasn't being handled"; +#endif + return false; + } + if (!penDevices.contains(penInfo.pointerInfo.sourceDevice)) { +#ifdef KRITA + dbgTablet << "Device is gone from the registration???"; +#endif + // TODO: re-register device? + penPointers.remove(penInfo.pointerInfo.pointerId); + return false; + } + + // penLeave + sendProximityTabletEvent(QEvent::TabletLeaveProximity, penInfo); + + penPointers.remove(penInfo.pointerInfo.pointerId); + + return false; +} + +bool handleSinglePenUpdate(PenPointerItem &penPointerItem, + const POINTER_PEN_INFO &penInfo, + const PointerDeviceItem &device, + const bool shouldSynthesizeMouseEvent) { + QWidget *targetWidget; + if (penPointerItem.isCaptured()) { + if (penPointerItem.widgetIsIgnored) { + return false; + } + targetWidget = penPointerItem.activeWidget; + if (!targetWidget) { + return false; + } + } else { + QWidget *hwndWidget = + QWidget::find(reinterpret_cast(penInfo.pointerInfo.hwndTarget)); + if (!hwndWidget) { +#ifdef KRITA + dbgTablet << "HWND cannot be mapped to QWidget (what?)"; +#endif + return false; + } + { + // Check popup / modal widget + QWidget *modalWidget = QApplication::activePopupWidget(); + if (!modalWidget) { + modalWidget = QApplication::activeModalWidget(); + } + if (modalWidget && modalWidget != hwndWidget && + !modalWidget->isAncestorOf(hwndWidget)) { + return false; + } + } + { + QWindow *topLevelWindow = hwndWidget->windowHandle(); + if (topLevelWindow) { + penPointerItem.oneOverDpr = 1.0 / topLevelWindow->devicePixelRatio(); + } else { + penPointerItem.oneOverDpr = 1.0 / qApp->devicePixelRatio(); + } + } + QPoint posInHwndWidget = hwndWidget->mapFromGlobal( + QPoint(static_cast(penInfo.pointerInfo.ptPixelLocationRaw.x * + penPointerItem.oneOverDpr), + static_cast(penInfo.pointerInfo.ptPixelLocationRaw.y * + penPointerItem.oneOverDpr))); + targetWidget = hwndWidget->childAt(posInHwndWidget); + if (!targetWidget) { + // dbgTablet << "No childQWidget at cursor position"; + targetWidget = hwndWidget; + } + // penPointerItem.activeWidget = targetWidget; + } + + bool handled = sendPositionalTabletEvent(targetWidget, QEvent::TabletMove, + penInfo, device, penPointerItem, + shouldSynthesizeMouseEvent); + return handled; +} + +bool handlePenUpdateMsg(const POINTER_PEN_INFO &penInfo) { + auto currentPointerIt = penPointers.find(penInfo.pointerInfo.pointerId); + if (currentPointerIt == penPointers.end()) { + // dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId << "wasn't being + // handled"; + return false; + } + + const auto devIt = penDevices.find(penInfo.pointerInfo.sourceDevice); + if (devIt == penDevices.end()) { +#ifdef KRITA + dbgTablet << "Device not registered???"; +#endif + return false; + } + + // UINT32 entriesCount = 0; + // if (!api.GetPointerPenInfoHistory(penInfo.pointerInfo.pointerId, + // &entriesCount, nullptr)) { + // dbgTablet << "GetPointerPenInfoHistory (getting count) failed"; + // return false; + // } + UINT32 entriesCount = penInfo.pointerInfo.historyCount; + // dbgTablet << "entriesCount:" << entriesCount; + bool handled = false; + if (entriesCount != 1) { + QVector penInfoArray(entriesCount); + if (!api.GetPointerPenInfoHistory(penInfo.pointerInfo.pointerId, + &entriesCount, penInfoArray.data())) { +#ifdef KRITA + dbgTablet << "GetPointerPenInfoHistory failed"; +#endif + return false; + } + bool handled = false; + // The returned array is in reverse chronological order + const auto rbegin = penInfoArray.rbegin(); + const auto rend = penInfoArray.rend(); + const auto rlast = + rend - 1; // Only synthesize mouse event for the last one + for (auto it = rbegin; it != rend; ++it) { + handled |= handleSinglePenUpdate( + *currentPointerIt, *it, *devIt, + it == rlast); // Bitwise OR doesn't short circuit + } + } else { + handled = handleSinglePenUpdate(*currentPointerIt, penInfo, *devIt, true); + } + return handled; +} + +bool handlePenDownMsg(const POINTER_PEN_INFO &penInfo) { + // PointerFlagsWrapper pointerFlags = + // PointerFlagsWrapper::fromPenInfo(penInfo); + // if (!pointerFlags.isPrimary()) { + // // Don't handle non-primary pointer messages for now + // return false; + // } + auto currentPointerIt = penPointers.find(penInfo.pointerInfo.pointerId); + if (currentPointerIt == penPointers.end()) { +#ifdef KRITA + dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId + << "wasn't being handled"; +#endif + return false; + } + currentPointerIt->hwnd = + penInfo.pointerInfo + .hwndTarget; // They *should* be the same, but just in case + QWidget *hwndWidget = + QWidget::find(reinterpret_cast(penInfo.pointerInfo.hwndTarget)); + if (!hwndWidget) { +#ifdef KRITA + dbgTablet << "HWND cannot be mapped to QWidget (what?)"; +#endif + return false; + } + { + QWindow *topLevelWindow = hwndWidget->windowHandle(); + if (topLevelWindow) { + currentPointerIt->oneOverDpr = 1.0 / topLevelWindow->devicePixelRatio(); + } else { + currentPointerIt->oneOverDpr = 1.0 / qApp->devicePixelRatio(); + } + } + QPoint posInHwndWidget = hwndWidget->mapFromGlobal( + QPoint(static_cast(penInfo.pointerInfo.ptPixelLocationRaw.x * + currentPointerIt->oneOverDpr), + static_cast(penInfo.pointerInfo.ptPixelLocationRaw.y * + currentPointerIt->oneOverDpr))); + QWidget *targetWidget = hwndWidget->childAt(posInHwndWidget); + if (!targetWidget) { +#ifdef KRITA + dbgTablet << "No childQWidget at cursor position"; +#endif + targetWidget = hwndWidget; + } + + currentPointerIt->activeWidget = targetWidget; + currentPointerIt->widgetIsCaptured = true; + // dbgTablet << "QWidget" << targetWidget->windowTitle() << "is capturing + // pointer" << penInfo.pointerInfo.pointerId; + { + // Check popup / modal widget + QWidget *modalWidget = QApplication::activePopupWidget(); + if (!modalWidget) { + modalWidget = QApplication::activeModalWidget(); + } + if (modalWidget && modalWidget != hwndWidget && + !modalWidget->isAncestorOf(hwndWidget)) { + currentPointerIt->widgetIsIgnored = true; +#ifdef KRITA + dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId + << "is being captured but will be ignored"; +#endif + return false; + } + } + + // penDown + const auto devIt = penDevices.find(penInfo.pointerInfo.sourceDevice); + if (devIt == penDevices.end()) { +#ifdef KRITA + dbgTablet << "Device not registered???"; +#endif + return false; + } + + bool handled = + sendPositionalTabletEvent(targetWidget, QEvent::TabletPress, penInfo, + *devIt, *currentPointerIt, true); + currentPointerIt->widgetAcceptsPenEvent = handled; + if (!handled) { + // dbgTablet << "QWidget did not handle tablet down event"; + } + return handled; +} + +bool handlePenUpMsg(const POINTER_PEN_INFO &penInfo) { + auto currentPointerIt = penPointers.find(penInfo.pointerInfo.pointerId); + if (currentPointerIt == penPointers.end()) { +#ifdef KRITA + dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId + << "wasn't being handled"; +#endif + return false; + } + PenPointerItem &penPointerItem = *currentPointerIt; + + if (!penPointerItem.isCaptured()) { +#ifdef KRITA + dbgTablet << "Pointer wasn't captured"; +#endif + return false; + } + if (penPointerItem.widgetIsIgnored) { + penPointerItem.widgetIsCaptured = false; + penPointerItem.widgetIsIgnored = false; + return false; + } + + // penUp + QWidget *targetWidget = penPointerItem.activeWidget; + if (!targetWidget) { +#ifdef KRITA + dbgTablet << "Previously captured target has been deleted"; +#endif + penPointerItem.widgetIsCaptured = false; + return false; + } + + const auto devIt = penDevices.find(penInfo.pointerInfo.sourceDevice); + if (devIt == penDevices.end()) { +#ifdef KRITA + dbgTablet << "Device not registered???"; +#endif + return false; + } + + bool handled = + sendPositionalTabletEvent(targetWidget, QEvent::TabletRelease, penInfo, + *devIt, penPointerItem, true); + + // dbgTablet << "QWidget" << currentPointerIt->activeWidget->windowTitle() << + // "is releasing capture to pointer" << penInfo.pointerInfo.pointerId; + penPointerItem.widgetIsCaptured = false; + penPointerItem.widgetAcceptsPenEvent = false; + return handled; +} + +bool handlePointerMsg(const MSG &msg) { + if (!api.isLoaded()) { + qWarning() << "Windows 8 Pointer Input API functions not loaded"; + return false; + } + + int pointerId = GET_POINTERID_WPARAM(msg.wParam); + POINTER_INPUT_TYPE pointerType; + if (!api.GetPointerType(pointerId, &pointerType)) { +#ifdef KRITA + dbgTablet << "GetPointerType failed"; +#endif + return false; + } + if (pointerType != PT_PEN) { + // dbgTablet << "pointerType" << pointerType << "is not PT_PEN"; + return false; + } + + POINTER_PEN_INFO penInfo; + if (!api.GetPointerPenInfo(pointerId, &penInfo)) { +#ifdef KRITA + dbgTablet << "GetPointerPenInfo failed"; +#endif + return false; + } + + switch (msg.message) { + case WM_POINTERDOWN: + // dbgTablet << "WM_POINTERDOWN"; + break; + case WM_POINTERUP: + // dbgTablet << "WM_POINTERUP"; + break; + case WM_POINTERENTER: + // dbgTablet << "WM_POINTERENTER"; + break; + case WM_POINTERLEAVE: + // dbgTablet << "WM_POINTERLEAVE"; + break; + case WM_POINTERUPDATE: + // dbgTablet << "WM_POINTERUPDATE"; + break; + case WM_POINTERCAPTURECHANGED: + // dbgTablet << "WM_POINTERCAPTURECHANGED"; + break; + default: +#ifdef KRITA + dbgTablet << "I missed this message: " << msg.message; +#endif + break; + } + // dbgTablet << " hwnd: " << penInfo.pointerInfo.hwndTarget; + // dbgTablet << " msg hwnd: " << msg.hwnd; + // dbgTablet << " pointerId: " << pointerId; + // dbgTablet << " sourceDevice:" << penInfo.pointerInfo.sourceDevice; + // dbgTablet << " pointerFlags:" << penInfo.pointerInfo.pointerFlags; + // dbgTablet << " btnChgType: " << penInfo.pointerInfo.ButtonChangeType; + // dbgTablet << " penFlags: " << penInfo.penFlags; + // dbgTablet << " penMask: " << penInfo.penMask; + // dbgTablet << " pressure: " << penInfo.pressure; + // dbgTablet << " rotation: " << penInfo.rotation; + // dbgTablet << " tiltX: " << penInfo.tiltX; + // dbgTablet << " tiltY: " << penInfo.tiltY; + // dbgTablet << " ptPixelLocationRaw: " << + // penInfo.pointerInfo.ptPixelLocationRaw; + // dbgTablet << " ptHimetricLocationRaw:" << + // penInfo.pointerInfo.ptHimetricLocationRaw; + // RECT pointerDeviceRect, displayRect; + // if (!api.GetPointerDeviceRects(penInfo.pointerInfo.sourceDevice, + // &pointerDeviceRect, &displayRect)) { + // dbgTablet << "GetPointerDeviceRects failed"; + // return false; + // } + // dbgTablet << " pointerDeviceRect:" << pointerDeviceRect; + // dbgTablet << " displayRect:" << displayRect; + // dbgTablet << " scaled X:" << + // static_cast(penInfo.pointerInfo.ptHimetricLocationRaw.x) / + // (pointerDeviceRect.right - pointerDeviceRect.left) * (displayRect.right - + // displayRect.left); + // dbgTablet << " scaled Y:" << + // static_cast(penInfo.pointerInfo.ptHimetricLocationRaw.y) / + // (pointerDeviceRect.bottom - pointerDeviceRect.top) * (displayRect.bottom - + // displayRect.top); + + switch (msg.message) { + case WM_POINTERDOWN: + return handlePenDownMsg(penInfo); + case WM_POINTERUP: + return handlePenUpMsg(penInfo); + case WM_POINTERENTER: + return handlePenEnterMsg(penInfo); + case WM_POINTERLEAVE: + return handlePenLeaveMsg(penInfo); + case WM_POINTERUPDATE: + return handlePenUpdateMsg(penInfo); + case WM_POINTERCAPTURECHANGED: +// TODO: Should this event be handled? +#ifdef KRITA + dbgTablet << "FIXME: WM_POINTERCAPTURECHANGED isn't handled"; +#endif + break; + } + + return false; +} + +} // namespace + +#endif // _WIN32 diff --git a/toonz/sources/toonz/kis_tablet_support_win8.h b/toonz/sources/toonz/kis_tablet_support_win8.h new file mode 100644 index 0000000..cb3c0e1 --- /dev/null +++ b/toonz/sources/toonz/kis_tablet_support_win8.h @@ -0,0 +1,73 @@ +/* +* This file is based on the Windows Pointer Input Message support code files by +* Alvin Wong. +* Notwithstanding the license specified in this repository, this file is +* redistributed under BSD 2-Clause license written below in order to keep +* backporting available. +* +* All contributions by Alvin Wong: +* Copyright (c) 2017 Alvin Wong +* All rights reserved. +* +* All other contributions: +* Copyright (c) 2018, the respective contributors. +* All rights reserved. +* +* Each contributor holds copyright over their respective contributions. +* The project versioning (Git) records all such contribution source information. +* +* Redistribution and use in source and binary forms, with or without +- modification, are permitted provided that the following conditions +- are met: +- +- 1. Redistributions of source code must retain the above copyright +- notice, this list of conditions and the following disclaimer. +- 2. Redistributions in binary form must reproduce the above copyright +- notice, this list of conditions and the following disclaimer in the +- documentation and/or other materials provided with the distribution. +- +- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +- IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef KIS_TABLET_SUPPORT_WIN8_H +#define KIS_TABLET_SUPPORT_WIN8_H + +#include + +#ifdef _WIN32 + +#ifdef KRITA +#include + +class KRITAUI_EXPORT KisTabletSupportWin8 : public QAbstractNativeEventFilter +#else +class KisTabletSupportWin8 : public QAbstractNativeEventFilter +#endif +{ + Q_DISABLE_COPY(KisTabletSupportWin8) + +public: + static bool isAvailable(); + static bool isPenDeviceAvailable(); + + KisTabletSupportWin8() = default; + ~KisTabletSupportWin8() = default; + + bool init(); + // void registerPointerDeviceNotifications(); + virtual bool nativeEventFilter(const QByteArray &eventType, void *message, + long *result) override; +}; + +#endif // _WIN32 + +#endif // KIS_TABLET_SUPPORT_WIN8_H diff --git a/toonz/sources/toonz/layerheaderpanel.cpp b/toonz/sources/toonz/layerheaderpanel.cpp index 429f096..8187f38 100644 --- a/toonz/sources/toonz/layerheaderpanel.cpp +++ b/toonz/sources/toonz/layerheaderpanel.cpp @@ -77,9 +77,9 @@ void LayerHeaderPanel::paintEvent(QPaintEvent *event) { ? m_viewer->getLayerHeaderLockOverImage() : m_viewer->getLayerHeaderLockImage()); - drawIcon(p, PredefinedRect::EYE, boost::none, preview); - drawIcon(p, PredefinedRect::PREVIEW_LAYER, boost::none, camstand); - drawIcon(p, PredefinedRect::LOCK, boost::none, lock); + drawIcon(p, PredefinedRect::PANEL_EYE, boost::none, preview); + drawIcon(p, PredefinedRect::PANEL_PREVIEW_LAYER, boost::none, camstand); + drawIcon(p, PredefinedRect::PANEL_LOCK, boost::none, lock); QRect numberRect = o->rect(PredefinedRect::LAYER_NUMBER); @@ -91,7 +91,7 @@ void LayerHeaderPanel::paintEvent(QPaintEvent *event) { } QRect nameRect = - o->rect(PredefinedRect::LAYER_NAME).adjusted(leftadj, 0, -1, 0); + o->rect(PredefinedRect::PANEL_LAYER_NAME).adjusted(leftadj, 0, -1, 0); p.drawText(nameRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, QObject::tr("Layer name")); diff --git a/toonz/sources/toonz/levelcommand.cpp b/toonz/sources/toonz/levelcommand.cpp index 665d321..4ae2d12 100644 --- a/toonz/sources/toonz/levelcommand.cpp +++ b/toonz/sources/toonz/levelcommand.cpp @@ -25,8 +25,6 @@ #include "tundo.h" #include "tconvert.h" -#include "cellselection.h" -#include "filmstripselection.h" #include "tlevel_io.h" #include "ttoonzimage.h" #include "tsystem.h" @@ -360,14 +358,14 @@ void revertTo(bool isCleanedUp) { /*-- Revert可能なLevelタイプの条件 --*/ if ((isCleanedUp && type == TZP_XSHLEVEL) || (!isCleanedUp && (type == TZP_XSHLEVEL || type == PLI_XSHLEVEL || - (type == OVL_XSHLEVEL && ext != "psd")))) { + type == OVL_XSHLEVEL))) { levels.insert(level); selectionContainLevel = true; } } if (levels.empty() || !selectionContainLevel) { DVGui::error( - QObject::tr("The Revert to Last Saved command is not supported for " + QObject::tr("The Reload command is not supported for " "the current selection.")); return; } diff --git a/toonz/sources/toonz/levelsettingspopup.cpp b/toonz/sources/toonz/levelsettingspopup.cpp index b440524..348f1db 100644 --- a/toonz/sources/toonz/levelsettingspopup.cpp +++ b/toonz/sources/toonz/levelsettingspopup.cpp @@ -28,7 +28,6 @@ #include "toonz/txsheethandle.h" #include "toonz/txshlevelhandle.h" #include "toonz/tcolumnhandle.h" -#include "toonz/txsheethandle.h" #include "toonz/toonzscene.h" #include "toonz/txshleveltypes.h" #include "toonz/levelproperties.h" diff --git a/toonz/sources/toonz/linetestpane.cpp b/toonz/sources/toonz/linetestpane.cpp index c6b938f..5d53a88 100644 --- a/toonz/sources/toonz/linetestpane.cpp +++ b/toonz/sources/toonz/linetestpane.cpp @@ -5,7 +5,6 @@ #include "xsheetdragtool.h" #include "toutputproperties.h" #include "tapp.h" -#include "toutputproperties.h" #include "toonz/tcolumnhandle.h" #include "toonz/txshlevelhandle.h" #include "toonz/toonzscene.h" diff --git a/toonz/sources/toonz/main.cpp b/toonz/sources/toonz/main.cpp index 4ddea24..8fb85fe 100644 --- a/toonz/sources/toonz/main.cpp +++ b/toonz/sources/toonz/main.cpp @@ -62,6 +62,9 @@ #include "tsimplecolorstyles.h" #include "toonz/imagestyles.h" #include "tvectorbrushstyle.h" +#include "tfont.h" + +#include "kis_tablet_support_win8.h" #ifdef MACOSX #include "tipc.h" @@ -89,17 +92,10 @@ TEnv::IntVar EnvSoftwareCurrentFontSize("SoftwareCurrentFontSize", 12); const char *applicationFullName = "LineTest 6.4 Beta"; const char *rootVarName = "LINETESTROOT"; const char *systemVarPrefix = "LINETEST"; -#else -const char *applicationName = "OpenToonz"; -const char *applicationVersion = "1.2"; -const char *applicationRevision = "1"; -const char *dllRelativePath = "./toonz6.app/Contents/Frameworks"; #endif TEnv::IntVar EnvSoftwareCurrentFontSize("SoftwareCurrentFontSize", 12); -const char *applicationFullName = - "OpenToonz 1.2.1"; // next will be 1.3 (not 1.3.0) const char *rootVarName = "TOONZROOT"; const char *systemVarPrefix = "TOONZ"; @@ -115,9 +111,10 @@ void qt_mac_set_menubar_merge(bool enable); static void fatalError(QString msg) { DVGui::MsgBoxInPopup( - CRITICAL, msg + "\n" + - QObject::tr("Installing %1 again could fix the problem.") - .arg(applicationFullName)); + CRITICAL, + msg + "\n" + + QObject::tr("Installing %1 again could fix the problem.") + .arg(QString::fromStdString(TEnv::getApplicationFullName()))); exit(0); } //----------------------------------------------------------------------------- @@ -154,12 +151,8 @@ DV_IMPORT_API void initColorFx(); */ static void initToonzEnv(QHash &argPathValues) { StudioPalette::enable(true); - - TEnv::setApplication(applicationName, applicationVersion, - applicationRevision); TEnv::setRootVarName(rootVarName); TEnv::setSystemVarPrefix(systemVarPrefix); - TEnv::setDllRelativeDir(TFilePath(dllRelativePath)); QHash::const_iterator i = argPathValues.constBegin(); while (i != argPathValues.constEnd()) { @@ -172,9 +165,8 @@ static void initToonzEnv(QHash &argPathValues) { QCoreApplication::setOrganizationName("OpenToonz"); QCoreApplication::setOrganizationDomain(""); - QString fullApplicationNameQStr = - QString(applicationName) + " " + applicationVersion; - QCoreApplication::setApplicationName(fullApplicationNameQStr); + QCoreApplication::setApplicationName( + QString::fromStdString(TEnv::getApplicationFullName())); /*-- TOONZROOTのPathの確認 --*/ // controllo se la xxxroot e' definita e corrisponde ad un folder esistente @@ -631,7 +623,7 @@ int main(int argc, char *argv[]) { QString currentStyle = Preferences::instance()->getCurrentStyleSheetPath(); a.setStyleSheet(currentStyle); - w.setWindowTitle(applicationFullName); + w.setWindowTitle(QString::fromStdString(TEnv::getApplicationFullName())); if (TEnv::getIsPortable()) { splash.showMessage(offsetStr + "Starting OpenToonz Portable ...", Qt::AlignCenter, Qt::white); @@ -682,16 +674,29 @@ int main(int argc, char *argv[]) { } QFont *myFont; - std::string fontName = - Preferences::instance()->getInterfaceFont().toStdString(); - std::string isBold = - Preferences::instance()->getInterfaceFontWeight() ? "Yes" : "No"; - myFont = new QFont(QString::fromStdString(fontName)); + QString fontName = Preferences::instance()->getInterfaceFont(); + QString fontStyle = Preferences::instance()->getInterfaceFontStyle(); + + TFontManager *fontMgr = TFontManager::instance(); + std::vector typefaces; + bool isBold = false, isItalic = false, hasKerning = false; + try { + fontMgr->loadFontNames(); + fontMgr->setFamily(fontName.toStdWString()); + fontMgr->getAllTypefaces(typefaces); + isBold = fontMgr->isBold(fontName, fontStyle); + isItalic = fontMgr->isItalic(fontName, fontStyle); + hasKerning = fontMgr->hasKerning(); + } catch (TFontCreationError &) { + // Do nothing. A default font should load + } + + myFont = new QFont(fontName); myFont->setPixelSize(EnvSoftwareCurrentFontSize); - if (strcmp(isBold.c_str(), "Yes") == 0) - myFont->setBold(true); - else - myFont->setBold(false); + myFont->setBold(isBold); + myFont->setItalic(isItalic); + myFont->setKerning(hasKerning); + a.setFont(*myFont); QAction *action = CommandManager::instance()->getAction("MI_OpenTMessage"); @@ -720,6 +725,17 @@ int main(int argc, char *argv[]) { #endif #endif +#ifdef _WIN32 + if (Preferences::instance()->isWinInkEnabled()) { + KisTabletSupportWin8 *penFilter = new KisTabletSupportWin8(); + if (penFilter->init()) { + a.installNativeEventFilter(penFilter); + } else { + delete penFilter; + } + } +#endif + a.installEventFilter(TApp::instance()); int ret = a.exec(); diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 26e4b63..289f81a 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -57,8 +57,6 @@ #include #include -extern const char *applicationFullName; - TEnv::IntVar ViewCameraToggleAction("ViewCameraToggleAction", 1); TEnv::IntVar ViewTableToggleAction("ViewTableToggleAction", 1); TEnv::IntVar FieldGuideToggleAction("FieldGuideToggleAction", 0); @@ -348,13 +346,12 @@ void Room::load(const TFilePath &fp) { dynamic_cast(pane->widget())->setPoolIndex(index); } - /*-- もしRoomにComboViewerがロードされたら、centralWidgetとして登録する --*/ - if (paneObjectName == "ComboViewer") - setCentralViewerPanel(qobject_cast(pane)); - settings.endGroup(); } + // resolve resize events here to avoid unwanted minimize of floating viewer + qApp->processEvents(); + DockLayout::State state(geometries, settings.value("hierarchy").toString()); layout->restoreState(state); @@ -494,7 +491,7 @@ void MainWindow::changeWindowTitle() { if (name.isEmpty()) name = tr("Untitled"); - name += " : " + QString::fromLatin1(applicationFullName); + name += " : " + QString::fromStdString(TEnv::getApplicationFullName()); setWindowTitle(name); } @@ -546,20 +543,6 @@ void MainWindow::refreshWriteSettings() { writeSettings(); } //----------------------------------------------------------------------------- void MainWindow::readSettings(const QString &argumentLayoutFileName) { - TFilePath fp(ToonzFolder::getMyModuleDir() + TFilePath(mySettingsFileName)); - QSettings mySettings(toQString(fp), QSettings::IniFormat); - /*-- Palette-PageViewerのチップサイズのロード --*/ - mySettings.beginGroup("PaletteChipSizes"); - { - PaletteViewerGUI::ChipSizeManager::instance()->chipSize_Palette = - mySettings.value("PaletteViewer", 2).toInt(); - PaletteViewerGUI::ChipSizeManager::instance()->chipSize_Cleanup = - mySettings.value("CleanupSettings", 0).toInt(); - PaletteViewerGUI::ChipSizeManager::instance()->chipSize_Studio = - mySettings.value("StudioPalette", 1).toInt(); - } - mySettings.endGroup(); - QTabBar *roomTabWidget = m_topBar->getRoomTabWidget(); /*-- Pageを追加すると同時にMenubarを追加する --*/ @@ -653,7 +636,7 @@ void MainWindow::readSettings(const QString &argumentLayoutFileName) { writeRoomList(rooms); // Imposto la stanza corrente - fp = ToonzFolder::getRoomsFile(currentRoomFileName); + TFilePath fp = ToonzFolder::getRoomsFile(currentRoomFileName); Tifstream is(fp); std::string currentRoomName; is >> currentRoomName; @@ -670,38 +653,6 @@ void MainWindow::readSettings(const QString &argumentLayoutFileName) { } RecentFiles::instance()->loadRecentFiles(); - - QStringList roomNames; - roomNames << "InknPaint" - << "Cleanup" - << "PltEdit" - << "Schematic" - << "QAR"; - /*--- ComboViewerのパーツのShow/Hideの再現 ---*/ - mySettings.beginGroup("ComboViewerPartsVisible"); - { - for (int r = 0; r < roomNames.size(); r++) { - QString tmpRoomName = roomNames.at(r); - Room *tmpRoom = getRoomByName(tmpRoomName); - if (tmpRoom) { - ComboViewerPanel *cvp = tmpRoom->getCentralViewerPanel(); - if (cvp) { - if (r == 0) // InknPaintRoom - TApp::instance()->setInknPaintViewerPanel(cvp); - mySettings.beginGroup(tmpRoomName); - cvp->setShowHideFlag(CVPARTS_TOOLBAR, - mySettings.value("Toolbar", true).toBool()); - cvp->setShowHideFlag(CVPARTS_TOOLOPTIONS, - mySettings.value("ToolOptions", true).toBool()); - cvp->setShowHideFlag(CVPARTS_FLIPCONSOLE, - mySettings.value("Console", true).toBool()); - cvp->updateShowHide(); - mySettings.endGroup(); - } - } - } - } - mySettings.endGroup(); } //----------------------------------------------------------------------------- @@ -745,56 +696,6 @@ void MainWindow::writeSettings() { QSettings settings(toQString(fp), QSettings::IniFormat); settings.setValue("MainWindowGeometry", saveGeometry()); - - // Recent Files - // RecentFiles::instance()->saveRecentFiles(); - - fp = ToonzFolder::getMyModuleDir() + TFilePath(mySettingsFileName); - QSettings mySettings(toQString(fp), QSettings::IniFormat); - - /*--- Palette-PageViewerのチップサイズの保存 ---*/ - mySettings.beginGroup("PaletteChipSizes"); - { - mySettings.setValue( - "PaletteViewer", - PaletteViewerGUI::ChipSizeManager::instance()->chipSize_Palette); - mySettings.setValue( - "CleanupSettings", - PaletteViewerGUI::ChipSizeManager::instance()->chipSize_Cleanup); - mySettings.setValue( - "StudioPalette", - PaletteViewerGUI::ChipSizeManager::instance()->chipSize_Studio); - } - mySettings.endGroup(); - - QStringList roomNames; - roomNames << "InknPaint" - << "Cleanup" - << "PltEdit" - << "Schematic" - << "QAR"; - /*--- ComboViewerのパーツのShow/Hideの保存 ---*/ - mySettings.beginGroup("ComboViewerPartsVisible"); - { - for (int r = 0; r < roomNames.size(); r++) { - QString tmpRoomName = roomNames.at(r); - Room *tmpRoom = getRoomByName(tmpRoomName); - if (tmpRoom) { - ComboViewerPanel *cvp = tmpRoom->getCentralViewerPanel(); - if (cvp) { - mySettings.beginGroup(tmpRoomName); - mySettings.setValue("Toolbar", cvp->getShowHideFlag(CVPARTS_TOOLBAR)); - mySettings.setValue("ToolOptions", - cvp->getShowHideFlag(CVPARTS_TOOLOPTIONS)); - mySettings.setValue("Console", - cvp->getShowHideFlag(CVPARTS_FLIPCONSOLE)); - cvp->updateShowHide(); - mySettings.endGroup(); - } - } - } - } - mySettings.endGroup(); } //----------------------------------------------------------------------------- @@ -814,15 +715,9 @@ Room *MainWindow::createCleanupRoom() { cleanupRoom->addDockWidget(viewer); layout->dockItem(viewer); ComboViewerPanel *cvp = qobject_cast(viewer); - if (cvp) { - /*- UI隠す -*/ - cvp->setShowHideFlag(CVPARTS_TOOLBAR, false); - cvp->setShowHideFlag(CVPARTS_TOOLOPTIONS, false); - cvp->setShowHideFlag(CVPARTS_FLIPCONSOLE, false); - cvp->updateShowHide(); - - cleanupRoom->setCentralViewerPanel(cvp); - } + if (cvp) + // hide all parts + cvp->setVisiblePartsFlag(CVPARTS_None); } // CleanupSettings @@ -861,11 +756,7 @@ Room *MainWindow::createPltEditRoom() { layout->dockItem(viewer); ComboViewerPanel *cvp = qobject_cast(viewer); - if (cvp) { - cvp->setShowHideFlag(CVPARTS_FLIPCONSOLE, false); - cvp->updateShowHide(); - pltEditRoom->setCentralViewerPanel(cvp); - } + if (cvp) cvp->setVisiblePartsFlag(CVPARTS_TOOLBAR | CVPARTS_TOOLOPTIONS); } // Palette @@ -917,12 +808,6 @@ Room *MainWindow::createInknPaintRoom() { if (viewer) { inknPaintRoom->addDockWidget(viewer); layout->dockItem(viewer); - - ComboViewerPanel *cvp = qobject_cast(viewer); - if (cvp) { - inknPaintRoom->setCentralViewerPanel(cvp); - TApp::instance()->setInknPaintViewerPanel(cvp); - } } // Palette @@ -1956,11 +1841,18 @@ void MainWindow::defineActions() { MenuViewCommandType); createToggle(MI_ACheck, tr("&Gap Check"), "", ACheckToggleAction ? 1 : 0, MenuViewCommandType); - createToggle(MI_ShiftTrace, tr("Shift and Trace"), "", false, - MenuViewCommandType); - createToggle(MI_EditShift, tr("Edit Shift"), "", false, MenuViewCommandType); + QAction *shiftTraceAction = createToggle(MI_ShiftTrace, tr("Shift and Trace"), + "", false, MenuViewCommandType); + shiftTraceAction->setIcon(QIcon(":Resources/shift_and_trace.svg")); + shiftTraceAction = createToggle(MI_EditShift, tr("Edit Shift"), "", false, + MenuViewCommandType); + shiftTraceAction->setIcon(QIcon(":Resources/shift_and_trace_edit.svg")); createToggle(MI_NoShift, tr("No Shift"), "", false, MenuViewCommandType); - createAction(MI_ResetShift, tr("Reset Shift"), "", MenuViewCommandType); + CommandManager::instance()->enable(MI_EditShift, false); + CommandManager::instance()->enable(MI_NoShift, false); + shiftTraceAction = + createAction(MI_ResetShift, tr("Reset Shift"), "", MenuViewCommandType); + shiftTraceAction->setIcon(QIcon(":Resources/shift_and_trace_reset.svg")); if (QGLPixelBuffer::hasOpenGLPbuffers()) createToggle(MI_RasterizePli, tr("&Visualize Vector As Raster"), "", @@ -2119,6 +2011,23 @@ void MainWindow::defineActions() { createRightClickMenuAction(MI_ResetInterpolation, tr("Reset Interpolation"), ""); + createRightClickMenuAction(MI_UseLinearInterpolation, + tr("Linear Interpolation"), ""); + createRightClickMenuAction(MI_UseSpeedInOutInterpolation, + tr("Speed In / Speed Out Interpolation"), ""); + createRightClickMenuAction(MI_UseEaseInOutInterpolation, + tr("Ease In / Ease Out Interpolation"), ""); + createRightClickMenuAction(MI_UseEaseInOutPctInterpolation, + tr("Ease In / Ease Out (%) Interpolation"), ""); + createRightClickMenuAction(MI_UseExponentialInterpolation, + tr("Exponential Interpolation"), ""); + createRightClickMenuAction(MI_UseExpressionInterpolation, + tr("Expression Interpolation"), ""); + createRightClickMenuAction(MI_UseFileInterpolation, tr("File Interpolation"), + ""); + createRightClickMenuAction(MI_UseConstantInterpolation, + tr("Constant Interpolation"), ""); + createRightClickMenuAction(MI_FoldColumns, tr("Fold Column"), ""); createRightClickMenuAction(MI_ActivateThisColumnOnly, tr("Show This Only"), @@ -2152,6 +2061,8 @@ void MainWindow::defineActions() { createRightClickMenuAction(MI_DeactivateUpperColumns, tr("Hide Upper Columns"), ""); + createRightClickMenuAction(MI_SeparateColors, tr("Separate Colors..."), ""); + createToolAction(T_Edit, "edit", tr("Animate Tool"), "A"); createToolAction(T_Selection, "selection", tr("Selection Tool"), "S"); createToolAction(T_Brush, "brush", tr("Brush Tool"), "B"); @@ -2186,7 +2097,7 @@ void MainWindow::defineActions() { createViewerAction(V_ZoomReset, tr("Reset View"), "Alt+0"); createViewerAction(V_ZoomFit, tr("Fit to Window"), "Alt+9"); createViewerAction(V_ActualPixelSize, tr("Actual Pixel Size"), "N"); - createViewerAction(V_FlipX, tr("Flip Viewer Horiontally"), ""); + createViewerAction(V_FlipX, tr("Flip Viewer Horizontally"), ""); createViewerAction(V_FlipY, tr("Flip Viewer Vertically"), ""); createViewerAction(V_ShowHideFullScreen, tr("Show//Hide Full Screen"), "Alt+F"); @@ -2419,9 +2330,9 @@ RecentFiles::~RecentFiles() {} void RecentFiles::addFilePath(QString path, FileType fileType) { QList files = - (fileType == Scene) - ? m_recentScenes - : (fileType == Level) ? m_recentLevels : m_recentFlipbookImages; + (fileType == Scene) ? m_recentScenes : (fileType == Level) + ? m_recentLevels + : m_recentFlipbookImages; int i; for (i = 0; i < files.size(); i++) if (files.at(i) == path) files.removeAt(i); @@ -2546,9 +2457,9 @@ void RecentFiles::saveRecentFiles() { QList RecentFiles::getFilesNameList(FileType fileType) { QList files = - (fileType == Scene) - ? m_recentScenes - : (fileType == Level) ? m_recentLevels : m_recentFlipbookImages; + (fileType == Scene) ? m_recentScenes : (fileType == Level) + ? m_recentLevels + : m_recentFlipbookImages; QList names; int i; for (i = 0; i < files.size(); i++) { @@ -2575,9 +2486,9 @@ void RecentFiles::refreshRecentFilesMenu(FileType fileType) { menu->setEnabled(false); else { CommandId clearActionId = - (fileType == Scene) - ? MI_ClearRecentScene - : (fileType == Level) ? MI_ClearRecentLevel : MI_ClearRecentImage; + (fileType == Scene) ? MI_ClearRecentScene : (fileType == Level) + ? MI_ClearRecentLevel + : MI_ClearRecentImage; menu->setActions(names); menu->addSeparator(); QAction *clearAction = CommandManager::instance()->getAction(clearActionId); diff --git a/toonz/sources/toonz/mainwindow.h b/toonz/sources/toonz/mainwindow.h index 1c07330..bf11637 100644 --- a/toonz/sources/toonz/mainwindow.h +++ b/toonz/sources/toonz/mainwindow.h @@ -30,18 +30,13 @@ class Room final : public TMainWindow { TFilePath m_path; QString m_name; - /*-- - * Room毎にComboViewerの初期状態をLoadするため、MainWindowからComboViewerにアクセスできるようにする。 - * --*/ - ComboViewerPanel *m_centralViewer; - public: #if QT_VERSION >= 0x050500 Room(QWidget *parent = 0, Qt::WindowFlags flags = 0) #else Room(QWidget *parent = 0, Qt::WFlags flags = 0) #endif - : TMainWindow(parent, flags), m_centralViewer(0) { + : TMainWindow(parent, flags) { } ~Room() {} @@ -52,11 +47,6 @@ public: QString getName() const { return m_name; } void setName(QString name) { m_name = name; } - ComboViewerPanel *getCentralViewerPanel() const { return m_centralViewer; } - void setCentralViewerPanel(ComboViewerPanel *cvp) { - if (!m_centralViewer) m_centralViewer = cvp; - } - void save(); void load(const TFilePath &fp); }; diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index 09ec119..996825b 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -277,6 +277,15 @@ #define MI_SetConstantSpeed "MI_SetConstantSpeed" #define MI_ResetInterpolation "MI_ResetInterpolation" +#define MI_UseLinearInterpolation "MI_UseLinearInterpolation" +#define MI_UseSpeedInOutInterpolation "MI_UseSpeedInOutInterpolation" +#define MI_UseEaseInOutInterpolation "MI_UseEaseInOutInterpolation" +#define MI_UseEaseInOutPctInterpolation "MI_UseEaseInOutPctInterpolation" +#define MI_UseExponentialInterpolation "MI_UseExponentialInterpolation" +#define MI_UseExpressionInterpolation "MI_UseExpressionInterpolation" +#define MI_UseFileInterpolation "MI_UseFileInterpolation" +#define MI_UseConstantInterpolation "MI_UseConstantInterpolation" + #define MI_ActivateThisColumnOnly "MI_ActivateThisColumnOnly" #define MI_ActivateSelectedColumns "MI_ActivateSelectedColumns" #define MI_ActivateAllColumns "MI_ActivateAllColumns" @@ -333,5 +342,6 @@ #define MI_LipSyncPopup "MI_LipSyncPopup" #define MI_AutoInputCellNumber "MI_AutoInputCellNumber" #define MI_TouchGestureControl "MI_TouchGestureControl" +#define MI_SeparateColors "MI_SeparateColors" #endif diff --git a/toonz/sources/toonz/mergecmapped.cpp b/toonz/sources/toonz/mergecmapped.cpp index e4863e9..20378b6 100644 --- a/toonz/sources/toonz/mergecmapped.cpp +++ b/toonz/sources/toonz/mergecmapped.cpp @@ -30,7 +30,6 @@ #include "timagecache.h" #include "tcolorstyles.h" #include "toonz/levelproperties.h" -#include "toonz/toonzscene.h" #include "toonz/childstack.h" #include "toonz/toonzimageutils.h" #include "tpaletteutil.h" diff --git a/toonz/sources/toonz/mergecolumns.cpp b/toonz/sources/toonz/mergecolumns.cpp index 027e8d0..6dcd82d 100644 --- a/toonz/sources/toonz/mergecolumns.cpp +++ b/toonz/sources/toonz/mergecolumns.cpp @@ -205,7 +205,7 @@ public: std::map::const_iterator it = m_images.begin(); std::vector fids; - m_level->setPalette(m_palette); + m_level->setPalette(m_palette->clone()); for (; it != m_images.end(); ++it) //, ++mit) { QString id = "MergeColumnsUndo" + QString::number(m_matchlineSessionId) + @@ -236,8 +236,8 @@ public: std::map::const_iterator it = m_images.begin(); for (; it != m_images.end(); ++it) //, ++mit) { - QString id = "MergeColumnsUndo" + QString::number((uintptr_t)this) + "-" + - QString::number(it->first.getNumber()); + QString id = "MergeColumnsUndo" + QString::number(m_matchlineSessionId) + + "-" + QString::number(it->first.getNumber()); TImageCache::instance()->remove(id); } } @@ -272,7 +272,7 @@ void mergeColumns(const std::set &columns) { static int MergeColumnsSessionId = 0; void mergeColumns(int column, int mColumn, bool isRedo) { - MergeColumnsSessionId++; + if (!isRedo) MergeColumnsSessionId++; TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); int start, end; xsh->getCellRange(column, start, end); @@ -353,11 +353,14 @@ void mergeColumns(int column, int mColumn, bool isRedo) { return; } - QString id = "MergeColumnsUndo" + QString::number(MergeColumnsSessionId) + - "-" + QString::number(fid.getNumber()); - TImageCache::instance()->add( - id, (timg) ? timg->cloneImage() : vimg->cloneImage()); - images[fid] = id; + if (!isRedo) { + QString id = "MergeColumnsUndo" + + QString::number(MergeColumnsSessionId) + "-" + + QString::number(fid.getNumber()); + TImageCache::instance()->add( + id, (timg) ? timg->cloneImage() : vimg->cloneImage()); + images[fid] = id; + } TAffine imgAff, matchAff; getColumnPlacement(imgAff, xsh, start + i, column, false); getColumnPlacement(matchAff, xsh, start + i, mColumn, false); diff --git a/toonz/sources/toonz/meshifypopup.cpp b/toonz/sources/toonz/meshifypopup.cpp index f371a09..cf57661 100644 --- a/toonz/sources/toonz/meshifypopup.cpp +++ b/toonz/sources/toonz/meshifypopup.cpp @@ -36,7 +36,6 @@ #include "toonz/levelset.h" #include "toonz/tstageobject.h" #include "toonz/tstageobjecttree.h" -#include "toonz/stage.h" #include "toonz/stagevisitor.h" // TnzExt includes diff --git a/toonz/sources/toonz/onionskinmaskgui.cpp b/toonz/sources/toonz/onionskinmaskgui.cpp index dc5175f..ad5bb7d 100644 --- a/toonz/sources/toonz/onionskinmaskgui.cpp +++ b/toonz/sources/toonz/onionskinmaskgui.cpp @@ -3,6 +3,11 @@ #include "onionskinmaskgui.h" #include "tapp.h" #include "toonz/tonionskinmaskhandle.h" +#include "toonz/tframehandle.h" +#include "toonz/txshlevelhandle.h" +#include "toonz/txsheethandle.h" +#include "toonz/tcolumnhandle.h" +#include "toonz/txshsimplelevel.h" #include "toonz/onionskinmask.h" @@ -76,6 +81,29 @@ void OnioniSkinMaskGUI::OnionSkinSwitcher::setSingleLevel() { setMask(osm); } +void OnioniSkinMaskGUI::OnionSkinSwitcher::clearFOS() { + OnionSkinMask osm = getMask(); + + for (int i = (osm.getFosCount() - 1); i >= 0; i--) + osm.setFos(osm.getFos(i), false); + + setMask(osm); +} + +void OnioniSkinMaskGUI::OnionSkinSwitcher::clearMOS() { + OnionSkinMask osm = getMask(); + + for (int i = (osm.getMosCount() - 1); i >= 0; i--) + osm.setMos(osm.getMos(i), false); + + setMask(osm); +} + +void OnioniSkinMaskGUI::OnionSkinSwitcher::clearOS() { + clearFOS(); + clearMOS(); +} + //------------------------------------------------------------------------------ void OnioniSkinMaskGUI::addOnionSkinCommand(QMenu *menu, bool isFilmStrip) { @@ -97,6 +125,23 @@ void OnioniSkinMaskGUI::addOnionSkinCommand(QMenu *menu, bool isFilmStrip) { menu->connect(extendOnionSkinToScene, SIGNAL(triggered()), &switcher, SLOT(setWholeScene())); } + OnionSkinMask osm = switcher.getMask(); + if (osm.getFosCount() || osm.getMosCount()) { + QAction *clearAllOnionSkins = menu->addAction( + QString(QObject::tr("Clear All Onion Skin Markers"))); + menu->connect(clearAllOnionSkins, SIGNAL(triggered()), &switcher, + SLOT(clearOS())); + } + if (osm.getFosCount() && osm.getMosCount()) { + QAction *clearFixedOnionSkins = menu->addAction( + QString(QObject::tr("Clear All Fixed Onion Skin Markers"))); + menu->connect(clearFixedOnionSkins, SIGNAL(triggered()), &switcher, + SLOT(clearFOS())); + QAction *clearRelativeOnionSkins = menu->addAction( + QString(QObject::tr("Clear All Relative Onion Skin Markers"))); + menu->connect(clearRelativeOnionSkins, SIGNAL(triggered()), &switcher, + SLOT(clearMOS())); + } } } else { QAction *activateOnionSkin = @@ -105,3 +150,66 @@ void OnioniSkinMaskGUI::addOnionSkinCommand(QMenu *menu, bool isFilmStrip) { SLOT(activate())); } } + +//------------------------------------------------------------------------------ + +void OnioniSkinMaskGUI::resetShiftTraceFrameOffset() { + auto setGhostOffset = [](int firstOffset, int secondOffset) { + OnionSkinMask osm = + TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask(); + osm.setShiftTraceGhostFrameOffset(0, firstOffset); + osm.setShiftTraceGhostFrameOffset(1, secondOffset); + TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(osm); + }; + + TApp *app = TApp::instance(); + if (app->getCurrentFrame()->isEditingLevel()) { + TXshSimpleLevel *level = app->getCurrentLevel()->getSimpleLevel(); + if (!level) { + setGhostOffset(0, 0); + return; + } + TFrameId fid = app->getCurrentFrame()->getFid(); + int firstOffset = (fid > level->getFirstFid()) ? -1 : 0; + int secondOffset = (fid < level->getLastFid()) ? 1 : 0; + + setGhostOffset(firstOffset, secondOffset); + } else { // when scene frame is selected + TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); + int col = app->getCurrentColumn()->getColumnIndex(); + TXshColumn *column = xsh->getColumn(col); + if (!column || column->isEmpty()) { + setGhostOffset(0, 0); + return; + } + int r0, r1; + column->getRange(r0, r1); + int row = app->getCurrentFrame()->getFrame(); + TXshCell cell = xsh->getCell(row, col); + int firstOffset = -1; + while (1) { + int r = row + firstOffset; + if (r < r0) { + firstOffset = 0; + break; + } + if (!xsh->getCell(r, col).isEmpty() && xsh->getCell(r, col) != cell) { + break; + } + firstOffset--; + } + int secondOffset = 1; + while (1) { + int r = row + secondOffset; + if (r > r1) { + secondOffset = 0; + break; + } + if (!xsh->getCell(r, col).isEmpty() && xsh->getCell(r, col) != cell) { + break; + } + secondOffset++; + } + setGhostOffset(firstOffset, secondOffset); + } +} diff --git a/toonz/sources/toonz/onionskinmaskgui.h b/toonz/sources/toonz/onionskinmaskgui.h index bbe0d3b..c9e514f 100644 --- a/toonz/sources/toonz/onionskinmaskgui.h +++ b/toonz/sources/toonz/onionskinmaskgui.h @@ -15,6 +15,8 @@ namespace OnioniSkinMaskGUI { // Da fare per la filmstrip!! void addOnionSkinCommand(QMenu *, bool isFilmStrip = false); +void resetShiftTraceFrameOffset(); + //============================================================================= // OnionSkinSwitcher //----------------------------------------------------------------------------- @@ -37,6 +39,9 @@ public slots: void deactivate(); void setWholeScene(); void setSingleLevel(); + void clearFOS(); + void clearMOS(); + void clearOS(); }; //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/outputsettingspopup.cpp b/toonz/sources/toonz/outputsettingspopup.cpp index f664f4c..141c68a 100644 --- a/toonz/sources/toonz/outputsettingspopup.cpp +++ b/toonz/sources/toonz/outputsettingspopup.cpp @@ -8,6 +8,7 @@ #include "tapp.h" #include "camerasettingspopup.h" #include "pane.h" +#include "boardsettingspopup.h" // TnzQt includes #include "toonzqt/menubarcommand.h" @@ -25,6 +26,7 @@ #include "toonz/preferences.h" #include "toutputproperties.h" #include "toonz/tcamera.h" +#include "toonz/boardsettings.h" // TnzBase includes #include "trasterfx.h" @@ -43,12 +45,13 @@ #include #include #include +#include //----------------------------------------------------------------------------- namespace { enum ResampleOption { - c_standard, + c_standard = 0, c_improved, c_high, @@ -65,9 +68,66 @@ enum ResampleOption { c_lanczos3, c_gauss, c_closestPixel, - c_bilinear + c_bilinear, + ResampleOptionCount }; +struct resampleInfo { + QString idString; + TRenderSettings::ResampleQuality quality; + QString uiString = ""; + resampleInfo(QString _idStr = "", + TRenderSettings::ResampleQuality _quality = + TRenderSettings::StandardResampleQuality) + : idString(_idStr), quality(_quality), uiString("") {} +}; + +QMap resampleInfoMap = { + {c_standard, + resampleInfo("Standard", TRenderSettings::StandardResampleQuality)}, + {c_improved, + resampleInfo("Improved", TRenderSettings::ImprovedResampleQuality)}, + {c_high, resampleInfo("High", TRenderSettings::HighResampleQuality)}, + {c_triangle, resampleInfo("Triangle filter", + TRenderSettings::Triangle_FilterResampleQuality)}, + {c_mitchell, resampleInfo("Mitchell-Netravali filter", + TRenderSettings::Mitchell_FilterResampleQuality)}, + {c_cubic5, resampleInfo("Cubic convolution, a = .5", + TRenderSettings::Cubic5_FilterResampleQuality)}, + {c_cubic75, resampleInfo("Cubic convolution, a = .75", + TRenderSettings::Cubic75_FilterResampleQuality)}, + {c_cubic1, resampleInfo("Cubic convolution, a = 1", + TRenderSettings::Cubic1_FilterResampleQuality)}, + {c_hann2, resampleInfo("Hann window, rad = 2", + TRenderSettings::Hann2_FilterResampleQuality)}, + {c_hann3, resampleInfo("Hann window, rad = 3", + TRenderSettings::Hann3_FilterResampleQuality)}, + {c_hamming2, resampleInfo("Hamming window, rad = 2", + TRenderSettings::Hamming2_FilterResampleQuality)}, + {c_hamming3, resampleInfo("Hamming window, rad = 3", + TRenderSettings::Hamming3_FilterResampleQuality)}, + {c_lanczos2, resampleInfo("Lanczos window, rad = 2", + TRenderSettings::Lanczos2_FilterResampleQuality)}, + {c_lanczos3, resampleInfo("Lanczos window, rad = 3", + TRenderSettings::Lanczos3_FilterResampleQuality)}, + {c_gauss, resampleInfo("Gaussian convolution", + TRenderSettings::Gauss_FilterResampleQuality)}, + {c_closestPixel, + resampleInfo("Closest Pixel (Nearest Neighbor)", + TRenderSettings::ClosestPixel_FilterResampleQuality)}, + {c_bilinear, + resampleInfo("Bilinear", + TRenderSettings::Bilinear_FilterResampleQuality)}}; + +ResampleOption quality2index(TRenderSettings::ResampleQuality quality) { + QMapIterator i(resampleInfoMap); + while (i.hasNext()) { + i.next(); + if (i.value().quality == quality) return i.key(); + } + return c_standard; +} + enum ChannelWidth { c_8bit, c_16bit }; enum DominantField { c_odd, c_even, c_none }; @@ -166,6 +226,11 @@ OutputSettingsPopup::OutputSettingsPopup(bool isPreview) otherSettingsLabel = new QLabel(tr("Other Settings"), this); otherSettingsFrame = new QFrame(this); m_renderButton = new QPushButton(tr("Render"), this); + + // Board + m_addBoard = new DVGui::CheckBox(tr("Add Clapperboard"), this); + m_boardSettingsBtn = new QPushButton(tr("Edit Clapperboard..."), this); + // Gamma m_gammaFld = new DVGui::DoubleLineEdit(); // Dominant Field @@ -214,25 +279,15 @@ OutputSettingsPopup::OutputSettingsPopup(bool isPreview) } // Resample Balance - QStringList resampleBalance; - resampleBalance << tr("Standard") << tr("Improved") << tr("High") - << tr("Triangle filter") << tr("Mitchell-Netravali filter") - << tr("Cubic convolution, a = .5") - << tr("Cubic convolution, a = .75") - << tr("Cubic convolution, a = 1") - << tr("Hann window, rad = 2") << tr("Hann window, rad = 3") - << tr("Hamming window, rad = 2") - << tr("Hamming window, rad = 3") - << tr("Lanczos window, rad = 2") - << tr("Lanczos window, rad = 3") << tr("Gaussian convolution") - << tr("Closest Pixel (Nearest Neighbor)") << tr("Bilinear"); - - m_resampleBalanceOm->addItems(resampleBalance); + translateResampleOptions(); + for (int i = 0; i < ResampleOptionCount; i++) { + m_resampleBalanceOm->addItem(resampleInfoMap[(ResampleOption)i].uiString, + resampleInfoMap[(ResampleOption)i].idString); + } // Channel Width - QStringList chWidth; - chWidth << tr("8 bit") << tr("16 bit"); - m_channelWidthOm->addItems(chWidth); + m_channelWidthOm->addItem(tr("8 bit"), "8 bit"); + m_channelWidthOm->addItem(tr("16 bit"), "16 bit"); if (!isPreview) { showOtherSettingsButton->setObjectName("OutputSettingsShowButton"); @@ -268,9 +323,10 @@ OutputSettingsPopup::OutputSettingsPopup(bool isPreview) addPresetButton->setObjectName("PushButton_NoPadding"); removePresetButton->setObjectName("PushButton_NoPadding"); /*-- OutputSettingsのプリセット登録の説 明--*/ - QString tooltip( - "Save current output settings.\nThe parameters to be saved are:\n\ -- Camera settings\n- Project folder to be saved in\n- File format\n- File options\n- Resample Balance\n- Channel width"); + QString tooltip = + tr("Save current output settings.\nThe parameters to be saved are:\n- " + "Camera settings\n- Project folder to be saved in\n- File format\n- " + "File options\n- Resample Balance\n- Channel width"); addPresetButton->setToolTip(tooltip); /*-- プリセットフォルダを調べ、コンボボックスにアイテムを格納する --*/ updatePresetComboItems(); @@ -457,39 +513,43 @@ OutputSettingsPopup::OutputSettingsPopup(bool isPreview) otherSettingsLay->setHorizontalSpacing(5); otherSettingsLay->setVerticalSpacing(10); { + // clapperboard + otherSettingsLay->addWidget(m_addBoard, 0, 0); + otherSettingsLay->addWidget(m_boardSettingsBtn, 0, 2, 1, 2); + // Gamma - otherSettingsLay->addWidget(new QLabel(tr("Gamma:"), this), 0, 0, + otherSettingsLay->addWidget(new QLabel(tr("Gamma:"), this), 1, 0, Qt::AlignRight | Qt::AlignVCenter); - otherSettingsLay->addWidget(m_gammaFld, 0, 1, 1, 3); + otherSettingsLay->addWidget(m_gammaFld, 1, 1, 1, 3); // Dominant Field otherSettingsLay->addWidget(new QLabel(tr("Dominant Field:"), this), - 1, 0, Qt::AlignRight | Qt::AlignVCenter); - otherSettingsLay->addWidget(m_dominantFieldOm, 1, 1, 1, 4); + 2, 0, Qt::AlignRight | Qt::AlignVCenter); + otherSettingsLay->addWidget(m_dominantFieldOm, 2, 1, 1, 4); // Scene Settings' FPS otherSettingsLay->addWidget( - new QLabel(tr("Frame Rate (linked to Scene Settings):"), this), 2, + new QLabel(tr("Frame Rate (linked to Scene Settings):"), this), 3, 0, Qt::AlignRight | Qt::AlignVCenter); - otherSettingsLay->addWidget(m_frameRateFld, 2, 1, 1, 3); + otherSettingsLay->addWidget(m_frameRateFld, 3, 1, 1, 3); // Strech otherSettingsLay->addWidget(new QLabel(tr("Stretch from FPS:"), this), - 3, 0, Qt::AlignRight | Qt::AlignVCenter); - otherSettingsLay->addWidget(m_stretchFromFld, 3, 1); - otherSettingsLay->addWidget(new QLabel(tr(" To:"), this), 3, 2, + 4, 0, Qt::AlignRight | Qt::AlignVCenter); + otherSettingsLay->addWidget(m_stretchFromFld, 4, 1); + otherSettingsLay->addWidget(new QLabel(tr(" To:"), this), 4, 2, Qt::AlignRight | Qt::AlignVCenter); - otherSettingsLay->addWidget(m_stretchToFld, 3, 3); + otherSettingsLay->addWidget(m_stretchToFld, 4, 3); // new in V6.1 // Multimedia rendering enum otherSettingsLay->addWidget( - new QLabel(tr("Multiple Rendering:"), this), 4, 0, + new QLabel(tr("Multiple Rendering:"), this), 5, 0, Qt::AlignRight | Qt::AlignVCenter); - otherSettingsLay->addWidget(m_multimediaOm, 4, 1, 1, 4); + otherSettingsLay->addWidget(m_multimediaOm, 5, 1, 1, 4); - otherSettingsLay->addWidget(m_doStereoscopy, 5, 0); - otherSettingsLay->addWidget(new QLabel(tr("Camera Shift:")), 5, 1, + otherSettingsLay->addWidget(m_doStereoscopy, 6, 0); + otherSettingsLay->addWidget(new QLabel(tr("Camera Shift:")), 6, 1, Qt::AlignRight | Qt::AlignVCenter); - otherSettingsLay->addWidget(m_stereoShift, 5, 2); + otherSettingsLay->addWidget(m_stereoShift, 6, 2); - otherSettingsLay->addLayout(bottomGridLay, 6, 0, 4, 5); + otherSettingsLay->addLayout(bottomGridLay, 7, 0, 4, 5); } otherSettingsLay->setColumnStretch(0, 0); otherSettingsLay->setColumnStretch(1, 0); @@ -548,6 +608,12 @@ OutputSettingsPopup::OutputSettingsPopup(bool isPreview) SLOT(onChannelWidthChanged(int))); if (!isPreview) { + // clapperboard + ret = ret && connect(m_addBoard, SIGNAL(stateChanged(int)), this, + SLOT(onAddBoardChecked(int))); + ret = ret && connect(m_boardSettingsBtn, SIGNAL(clicked()), this, + SLOT(onBoardSettingsBtnClicked())); + ret = ret && connect(m_gammaFld, SIGNAL(editingFinished()), SLOT(onGammaFldEditFinished())); ret = ret && connect(m_dominantFieldOm, SIGNAL(currentIndexChanged(int)), @@ -764,60 +830,8 @@ void OutputSettingsPopup::updateField() { m_applyShrinkChk->setCheckState( renderSettings.m_applyShrinkToViewer ? Qt::Checked : Qt::Unchecked); // resample - switch (renderSettings.m_quality) { - case TRenderSettings::ImprovedResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_improved); - break; - case TRenderSettings::HighResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_high); - break; - case TRenderSettings::StandardResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_standard); - break; - - case TRenderSettings::Mitchell_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_mitchell); - break; - case TRenderSettings::Cubic5_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_cubic5); - break; - case TRenderSettings::Cubic75_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_cubic75); - break; - case TRenderSettings::Cubic1_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_cubic1); - break; - case TRenderSettings::Hann2_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_hann2); - break; - case TRenderSettings::Hann3_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_hann3); - break; - case TRenderSettings::Hamming2_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_hamming2); - break; - case TRenderSettings::Hamming3_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_hamming3); - break; - case TRenderSettings::Lanczos2_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_lanczos2); - break; - case TRenderSettings::Lanczos3_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_lanczos3); - break; - case TRenderSettings::Gauss_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_gauss); - break; - case TRenderSettings::ClosestPixel_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_closestPixel); - break; - case TRenderSettings::Bilinear_FilterResampleQuality: - m_resampleBalanceOm->setCurrentIndex(c_bilinear); - break; - default: - m_resampleBalanceOm->setCurrentIndex(c_standard); - break; - } + m_resampleBalanceOm->setCurrentIndex( + (int)quality2index(renderSettings.m_quality)); // channel width switch (renderSettings.m_bpp) { @@ -862,6 +876,18 @@ void OutputSettingsPopup::updateField() { m_stretchToFld->setValue(renderSettings.m_timeStretchTo); m_frameRateFld->setValue(prop->getFrameRate()); + + // clapperboard + BoardSettings *boardSettings = prop->getBoardSettings(); + m_addBoard->setChecked(boardSettings->isActive()); + // clapperboard is only available with movie formats + if (isMovieType(m_fileFormat->currentText().toStdString())) { + m_addBoard->setEnabled(true); + m_boardSettingsBtn->setEnabled(m_addBoard->isChecked()); + } else { + m_addBoard->setEnabled(false); + m_boardSettingsBtn->setEnabled(false); + } } //----------------------------------------------------------------------------- @@ -960,6 +986,15 @@ void OutputSettingsPopup::onFormatChanged(const QString &str) { m_threadsComboOm->setDisabled(false); m_threadsComboOm->setCurrentIndex(2); } + + // clapperboard is only available with movie formats + if (isMovieType(str.toStdString())) { + m_addBoard->setEnabled(true); + m_boardSettingsBtn->setEnabled(m_addBoard->isChecked()); + } else { + m_addBoard->setEnabled(false); + m_boardSettingsBtn->setEnabled(false); + } } //----------------------------------------------------------------------------- @@ -1106,42 +1141,8 @@ void OutputSettingsPopup::onResampleChanged(int type) { if (!getCurrentScene()) return; TOutputProperties *prop = getProperties(); TRenderSettings rs = prop->getRenderSettings(); - if (type == c_improved) - rs.m_quality = TRenderSettings::ImprovedResampleQuality; - else if (type == c_high) - rs.m_quality = TRenderSettings::HighResampleQuality; - else if (type == c_standard) - rs.m_quality = TRenderSettings::StandardResampleQuality; - else if (type == c_triangle) - rs.m_quality = TRenderSettings::Triangle_FilterResampleQuality; - else if (type == c_mitchell) - rs.m_quality = TRenderSettings::Mitchell_FilterResampleQuality; - else if (type == c_cubic5) - rs.m_quality = TRenderSettings::Cubic5_FilterResampleQuality; - else if (type == c_cubic75) - rs.m_quality = TRenderSettings::Cubic75_FilterResampleQuality; - else if (type == c_cubic1) - rs.m_quality = TRenderSettings::Cubic1_FilterResampleQuality; - else if (type == c_hann2) - rs.m_quality = TRenderSettings::Hann2_FilterResampleQuality; - else if (type == c_hann3) - rs.m_quality = TRenderSettings::Hann3_FilterResampleQuality; - else if (type == c_hamming2) - rs.m_quality = TRenderSettings::Hamming2_FilterResampleQuality; - else if (type == c_hamming3) - rs.m_quality = TRenderSettings::Hamming3_FilterResampleQuality; - else if (type == c_lanczos2) - rs.m_quality = TRenderSettings::Lanczos2_FilterResampleQuality; - else if (type == c_lanczos3) - rs.m_quality = TRenderSettings::Lanczos3_FilterResampleQuality; - else if (type == c_gauss) - rs.m_quality = TRenderSettings::Gauss_FilterResampleQuality; - else if (type == c_closestPixel) - rs.m_quality = TRenderSettings::ClosestPixel_FilterResampleQuality; - else if (type == c_bilinear) - rs.m_quality = TRenderSettings::Bilinear_FilterResampleQuality; - else - rs.m_quality = TRenderSettings::StandardResampleQuality; + + rs.m_quality = resampleInfoMap[(ResampleOption)type].quality; prop->setRenderSettings(rs); TApp::instance()->getCurrentScene()->setDirtyFlag(true); if (m_presetCombo) m_presetCombo->setCurrentIndex(0); @@ -1335,11 +1336,13 @@ void OutputSettingsPopup::onAddPresetButtonPressed() { os.closeChild(); // Resample Balance - QString resq = m_resampleBalanceOm->currentText(); + QString resq = + resampleInfoMap[(ResampleOption)m_resampleBalanceOm->currentIndex()] + .idString; os.child("resquality") << resq.toStdString(); // Channel Width - QString chanw = m_channelWidthOm->currentText(); + QString chanw = m_channelWidthOm->currentData().toString(); os.child("bpp") << chanw.toStdString(); // 140503 iwasawa Frame Rate (Scene Settings) @@ -1380,6 +1383,29 @@ void OutputSettingsPopup::updatePresetComboItems() { } //----------------------------------------------------------------------------- + +void OutputSettingsPopup::translateResampleOptions() { + resampleInfoMap[c_standard].uiString = tr("Standard"); + resampleInfoMap[c_improved].uiString = tr("Improved"); + resampleInfoMap[c_high].uiString = tr("High"); + resampleInfoMap[c_triangle].uiString = tr("Triangle filter"); + resampleInfoMap[c_mitchell].uiString = tr("Mitchell-Netravali filter"); + resampleInfoMap[c_cubic5].uiString = tr("Cubic convolution, a = .5"); + resampleInfoMap[c_cubic75].uiString = tr("Cubic convolution, a = .75"); + resampleInfoMap[c_cubic1].uiString = tr("Cubic convolution, a = 1"); + resampleInfoMap[c_hann2].uiString = tr("Hann window, rad = 2"); + resampleInfoMap[c_hann3].uiString = tr("Hann window, rad = 3"); + resampleInfoMap[c_hamming2].uiString = tr("Hamming window, rad = 2"); + resampleInfoMap[c_hamming3].uiString = tr("Hamming window, rad = 3"); + resampleInfoMap[c_lanczos2].uiString = tr("Lanczos window, rad = 2"); + resampleInfoMap[c_lanczos3].uiString = tr("Lanczos window, rad = 3"); + resampleInfoMap[c_gauss].uiString = tr("Gaussian convolution"); + resampleInfoMap[c_closestPixel].uiString = + tr("Closest Pixel (Nearest Neighbor)"); + resampleInfoMap[c_bilinear].uiString = tr("Bilinear"); +} + +//----------------------------------------------------------------------------- /*! OutputSettingsのPreset削除 */ void OutputSettingsPopup::onRemovePresetButtonPressed() { @@ -1505,15 +1531,34 @@ void OutputSettingsPopup::onPresetSelected(const QString &str) { else if (tagName == "resquality") { std::string resq; is >> resq; - int index = m_resampleBalanceOm->findText(QString::fromStdString(resq)); - if (index >= 0) m_resampleBalanceOm->setCurrentIndex(index); + // first, search in the combobox item data. + int index = m_resampleBalanceOm->findData(QString::fromStdString(resq)); + // second, search in the combobox ui text (which may be translated). + // the second search is kept in order to keep backward compatibility. + if (index < 0) + index = m_resampleBalanceOm->findText(QString::fromStdString(resq)); + if (index >= 0) { + m_resampleBalanceOm->setCurrentIndex(index); + rs.m_quality = resampleInfoMap[(ResampleOption)index].quality; + } } // Channel Width else if (tagName == "bpp") { std::string chanw; is >> chanw; - int index = m_channelWidthOm->findText(QString::fromStdString(chanw)); - if (index >= 0) m_channelWidthOm->setCurrentIndex(index); + // first, search in the combobox item data. + int index = m_channelWidthOm->findData(QString::fromStdString(chanw)); + // second, search in the combobox ui text (which may be translated). + // the second search is kept in order to keep backward compatibility. + if (index < 0) + index = m_channelWidthOm->findText(QString::fromStdString(chanw)); + if (index >= 0) { + m_channelWidthOm->setCurrentIndex(index); + if (index == c_8bit) + rs.m_bpp = 32; + else + rs.m_bpp = 64; + } } // Frame Rate (Scene Settings) @@ -1574,6 +1619,21 @@ void OutputSettingsPopup::onFrameRateEditingFinished() { //----------------------------------------------------------------------------- +void OutputSettingsPopup::onAddBoardChecked(int state) { + BoardSettings *boardSettings = getProperties()->getBoardSettings(); + boardSettings->setActive(state == Qt::Checked); + + m_boardSettingsBtn->setEnabled(state == Qt::Checked); +} + +void OutputSettingsPopup::onBoardSettingsBtnClicked() { + std::cout << "board settings button clicked" << std::endl; + BoardSettingsPopup popup(this); + popup.exec(); +} + +//----------------------------------------------------------------------------- + OpenPopupCommandHandler openOutputSettingsPopup( MI_OutputSettings); OpenPopupCommandHandler openPreviewSettingsPopup( diff --git a/toonz/sources/toonz/outputsettingspopup.h b/toonz/sources/toonz/outputsettingspopup.h index 21668d3..99aeb0b 100644 --- a/toonz/sources/toonz/outputsettingspopup.h +++ b/toonz/sources/toonz/outputsettingspopup.h @@ -53,9 +53,14 @@ class OutputSettingsPopup : public DVGui::Dialog { CameraSettingsPopup *m_cameraSettings; QComboBox *m_presetCombo; + // clapperboard + DVGui::CheckBox *m_addBoard; + QPushButton *m_boardSettingsBtn; + bool m_isPreviewSettings; void updatePresetComboItems(); + void translateResampleOptions(); public: OutputSettingsPopup(bool isPreview = false); @@ -97,6 +102,9 @@ protected slots: void onCameraSettingsChanged(); /*-- Scene Settings のFPSを編集できるようにする --*/ void onFrameRateEditingFinished(); + // clapperboard + void onAddBoardChecked(int state); + void onBoardSettingsBtnClicked(); }; class PreviewSettingsPopup final : public OutputSettingsPopup { diff --git a/toonz/sources/toonz/penciltestpopup.cpp b/toonz/sources/toonz/penciltestpopup.cpp index 72498a3..a24894e 100644 --- a/toonz/sources/toonz/penciltestpopup.cpp +++ b/toonz/sources/toonz/penciltestpopup.cpp @@ -63,7 +63,6 @@ #include #include #include -#include #include #include #include @@ -72,7 +71,6 @@ #include #include #include -#include #ifdef _WIN32 #include @@ -1697,7 +1695,7 @@ void PencilTestPopup::onPreviousName() { //----------------------------------------------------------------------------- void PencilTestPopup::setToNextNewLevel() { - const std::auto_ptr nameBuilder(NameBuilder::getBuilder(L"")); + const std::unique_ptr nameBuilder(NameBuilder::getBuilder(L"")); TLevelSet* levelSet = TApp::instance()->getCurrentScene()->getScene()->getLevelSet(); diff --git a/toonz/sources/toonz/pltgizmopopup.cpp b/toonz/sources/toonz/pltgizmopopup.cpp index 9a77ffc..7cd428a 100644 --- a/toonz/sources/toonz/pltgizmopopup.cpp +++ b/toonz/sources/toonz/pltgizmopopup.cpp @@ -361,6 +361,11 @@ void modifyColor(const T &modifier) { TPaletteHandle *paletteHandle = TApp::instance()->getPaletteController()->getCurrentLevelPalette(); TPaletteP palette = paletteHandle->getPalette(); + if (!palette) { + QMessageBox::warning(0, QObject::tr("Error"), + QObject::tr("No Palette loaded.")); + return; + } if (palette->isLocked()) { QMessageBox::warning(0, QObject::tr("Warning"), QObject::tr("Palette is locked.")); diff --git a/toonz/sources/toonz/preferencespopup.cpp b/toonz/sources/toonz/preferencespopup.cpp index 5808025..73c23e4 100644 --- a/toonz/sources/toonz/preferencespopup.cpp +++ b/toonz/sources/toonz/preferencespopup.cpp @@ -24,7 +24,6 @@ #include "toonz/tscenehandle.h" #include "toonz/txshlevelhandle.h" #include "toonz/txshleveltypes.h" -#include "toonz/tscenehandle.h" #include "toonz/toonzscene.h" #include "toonz/tcamera.h" #include "toonz/levelproperties.h" @@ -35,9 +34,12 @@ #include "tsystem.h" #include "tfont.h" +#include "kis_tablet_support_win8.h" + // Qt includes #include #include +#include #include #include #include @@ -353,10 +355,37 @@ void PreferencesPopup::onDropdownShortcutsCycleOptionsChanged(int index) { } //----------------------------------------------------------------------------- +void PreferencesPopup::rebuilldFontStyleList() { + TFontManager *instance = TFontManager::instance(); + std::vector typefaces; + std::vector::iterator it; + QString font = m_interfaceFont->currentText(); + QString style = m_pref->getInterfaceFontStyle(); + try { + instance->loadFontNames(); + instance->setFamily(font.toStdWString()); + instance->getAllTypefaces(typefaces); + } catch (TFontCreationError &) { + it = typefaces.begin(); + typefaces.insert(it, style.toStdWString()); + } + m_interfaceFontStyle->clear(); + for (it = typefaces.begin(); it != typefaces.end(); ++it) + m_interfaceFontStyle->addItem(QString::fromStdWString(*it)); +} void PreferencesPopup::onInterfaceFontChanged(int index) { QString font = m_interfaceFont->currentText(); m_pref->setInterfaceFont(font.toStdString()); + + QString oldTypeface = m_interfaceFontStyle->currentText(); + rebuilldFontStyleList(); + if (!oldTypeface.isEmpty()) { + int newIndex = m_interfaceFontStyle->findText(oldTypeface); + if (newIndex < 0) newIndex = 0; + m_interfaceFontStyle->setCurrentIndex(newIndex); + } + if (font.contains("Comic Sans")) DVGui::warning(tr("Life is too short for Comic Sans")); if (font.contains("Wingdings")) @@ -365,8 +394,9 @@ void PreferencesPopup::onInterfaceFontChanged(int index) { //----------------------------------------------------------------------------- -void PreferencesPopup::onInterfaceFontWeightChanged(int index) { - m_pref->setInterfaceFontWeight(index); +void PreferencesPopup::onInterfaceFontStyleChanged(int index) { + QString style = m_interfaceFontStyle->itemText(index); + m_pref->setInterfaceFontStyle(style.toStdString()); } //----------------------------------------------------------------------------- @@ -481,6 +511,7 @@ void PreferencesPopup::onOnionDataChanged(const TPixel32 &, bool isDragging) { TApp::instance()->getCurrentScene()->notifySceneChanged(); TApp::instance()->getCurrentLevel()->notifyLevelViewChange(); + TApp::instance()->getCurrentOnionSkin()->notifyOnionSkinMaskChanged(); } //----------------------------------------------------------------------------- @@ -680,7 +711,7 @@ void PreferencesPopup::onStartupPopupChanged(int index) { //----------------------------------------------------------------------------- void PreferencesPopup::onKeyframeTypeChanged(int index) { - m_pref->setKeyframeType(index + 2); + m_pref->setKeyframeType(index + 1); } //----------------------------------------------------------------------------- @@ -781,8 +812,14 @@ void PreferencesPopup::onOnionSkinDuringPlaybackChanged(int index) { //----------------------------------------------------------------------------- +void PreferencesPopup::onOnionColorsForShiftAndTraceChanged(int index) { + m_pref->useOnionColorsForShiftAndTraceGhosts(index == Qt::Checked); +} + +//----------------------------------------------------------------------------- + void PreferencesPopup::onGuidedDrawingStyleChanged(int index) { - m_pref->setAnimatedGuidedDrawing(index); + m_pref->setAnimatedGuidedDrawing(index == 1); } //----------------------------------------------------------------------------- @@ -1201,6 +1238,20 @@ void PreferencesPopup::onCurrentColumnDataChanged(const TPixel32 &, m_pref->setCurrentColumnData(m_currentColumnColor->getColor()); } +//--------------------------------------------------------------------------------------- + +void PreferencesPopup::onEnableWinInkChanged(int index) { + m_pref->enableWinInk(index == Qt::Checked); +} + +//--------------------------------------------------------------------------------------- + +void PreferencesPopup::onRasterBackgroundColorChanged(const TPixel32 &color, + bool isDragging) { + if (isDragging) return; + m_pref->setRasterBackgroundColor(color); +} + //********************************************************************************** // PrefencesPopup's constructor //********************************************************************************** @@ -1211,6 +1262,12 @@ PreferencesPopup::PreferencesPopup() , m_inksOnly(0) , m_blanksCount(0) , m_blankColor(0) { + bool showTabletSettings = false; + +#ifdef _WIN32 + showTabletSettings = KisTabletSupportWin8::isAvailable(); +#endif + setWindowTitle(tr("Preferences")); setObjectName("PreferencesPopup"); @@ -1313,8 +1370,8 @@ PreferencesPopup::PreferencesPopup() new QLabel(tr("* Changes will take effect the next time you run Toonz")); note_interface->setStyleSheet("font-size: 10px; font: italic;"); - m_interfaceFont = new QComboBox(this); - m_interfaceFontWeight = new QComboBox(this); + m_interfaceFont = new QFontComboBox(this); + m_interfaceFontStyle = new QComboBox(this); m_colorCalibration = new QGroupBox(tr("Color Calibration using 3D Look-up Table *")); @@ -1350,6 +1407,12 @@ PreferencesPopup::PreferencesPopup() m_importPolicy = new QComboBox; + //--- Saving ------------------------------ + categoryList->addItem(tr("Saving")); + + ColorField *rasterBackgroundColor = + new ColorField(this, false, m_pref->getRasterBackgroundColor()); + //--- Import/Export ------------------------------ categoryList->addItem(tr("Import/Export")); m_ffmpegPathFileFld = new DVGui::FileField(this, QString("")); @@ -1496,9 +1559,11 @@ PreferencesPopup::PreferencesPopup() m_onionSkinVisibility = new CheckBox(tr("Onion Skin ON")); m_onionSkinDuringPlayback = new CheckBox(tr("Show Onion Skin During Playback")); - m_frontOnionColor = new ColorField(this, false, frontColor); - m_backOnionColor = new ColorField(this, false, backColor); - m_inksOnly = new DVGui::CheckBox(tr("Display Lines Only ")); + m_frontOnionColor = new ColorField(this, false, frontColor); + m_backOnionColor = new ColorField(this, false, backColor); + m_useOnionColorsForShiftAndTraceCB = new CheckBox( + tr("Use Onion Skin Colors for Reference Drawings of Shift and Trace")); + m_inksOnly = new DVGui::CheckBox(tr("Display Lines Only ")); m_inksOnly->setChecked(onlyInks); int thickness = m_pref->getOnionPaperThickness(); @@ -1538,6 +1603,19 @@ PreferencesPopup::PreferencesPopup() new QLabel(tr("* Changes will take effect the next time you run Toonz")); note_version->setStyleSheet("font-size: 10px; font: italic;"); + QLabel *note_tablet; + //--- Tablet Settings ------------------------------ + if (showTabletSettings) { + categoryList->addItem(tr("Tablet Settings")); + + m_enableWinInk = + new DVGui::CheckBox(tr("Enable Windows Ink Support* (EXPERIMENTAL)")); + + note_tablet = new QLabel( + tr("* Changes will take effect the next time you run Toonz")); + note_tablet->setStyleSheet("font-size: 10px; font: italic;"); + } + /*--- set default parameters ---*/ categoryList->setFixedWidth(160); categoryList->setCurrentRow(0); @@ -1661,32 +1739,10 @@ PreferencesPopup::PreferencesPopup() viewerZoomCenterComboBox->addItems(zoomCenters); viewerZoomCenterComboBox->setCurrentIndex(m_pref->getViewerZoomCenter()); - TFontManager *instance = TFontManager::instance(); - bool validFonts; - try { - instance->loadFontNames(); - validFonts = true; - } catch (TFontLibraryLoadingError &) { - validFonts = false; - // TMessage::error(toString(e.getMessage())); - } - - if (validFonts) { - std::vector names; - instance->getAllFamilies(names); + m_interfaceFont->setCurrentText(m_pref->getInterfaceFont()); - for (std::vector::iterator it = names.begin(); - it != names.end(); ++it) - m_interfaceFont->addItem(QString::fromStdWString(*it)); - - m_interfaceFont->setCurrentText(m_pref->getInterfaceFont()); - } - - QStringList fontStyles; - fontStyles << "Regular" - << "Bold"; - m_interfaceFontWeight->addItems(fontStyles); - m_interfaceFontWeight->setCurrentIndex(m_pref->getInterfaceFontWeight()); + rebuilldFontStyleList(); + m_interfaceFontStyle->setCurrentText(m_pref->getInterfaceFontStyle()); m_colorCalibration->setCheckable(true); m_colorCalibration->setChecked(m_pref->isColorCalibrationEnabled()); @@ -1846,11 +1902,12 @@ PreferencesPopup::PreferencesPopup() //--- Animation ------------------------------ QStringList list; - list << tr("Linear") << tr("Speed In / Speed Out") << tr("Ease In / Ease Out") - << tr("Ease In / Ease Out %"); + list << tr("Constant") << tr("Linear") << tr("Speed In / Speed Out") + << tr("Ease In / Ease Out") << tr("Ease In / Ease Out %") + << tr("Exponential") << tr("Expression ") << tr("File"); m_keyframeType->addItems(list); int keyframeType = m_pref->getKeyframeType(); - m_keyframeType->setCurrentIndex(keyframeType - 2); + m_keyframeType->setCurrentIndex(keyframeType - 1); m_animationStepField->setValue(m_pref->getAnimationStep()); //--- Preview ------------------------------ @@ -1870,11 +1927,14 @@ PreferencesPopup::PreferencesPopup() m_onionSkinDuringPlayback->setChecked(m_pref->getOnionSkinDuringPlayback()); m_frontOnionColor->setEnabled(m_pref->isOnionSkinEnabled()); m_backOnionColor->setEnabled(m_pref->isOnionSkinEnabled()); + m_useOnionColorsForShiftAndTraceCB->setChecked( + m_pref->areOnionColorsUsedForShiftAndTraceGhosts()); m_inksOnly->setEnabled(m_pref->isOnionSkinEnabled()); QStringList guidedDrawingStyles; guidedDrawingStyles << tr("Arrow Markers") << tr("Animated Guide"); m_guidedDrawingStyle->addItems(guidedDrawingStyles); - m_guidedDrawingStyle->setCurrentIndex(m_pref->getAnimatedGuidedDrawing()); + m_guidedDrawingStyle->setCurrentIndex(m_pref->getAnimatedGuidedDrawing() ? 1 + : 0); //--- Version Control ------------------------------ m_enableVersionControl->setChecked(m_pref->isSVNEnabled()); @@ -1882,6 +1942,9 @@ PreferencesPopup::PreferencesPopup() m_pref->isAutomaticSVNFolderRefreshEnabled()); checkForTheLatestVersionCB->setChecked(m_pref->isLatestVersionCheckEnabled()); + //--- Tablet Settings ------------------------------ + if (showTabletSettings) m_enableWinInk->setChecked(m_pref->isWinInkEnabled()); + /*--- layout ---*/ QHBoxLayout *mainLayout = new QHBoxLayout(); @@ -2092,8 +2155,8 @@ PreferencesPopup::PreferencesPopup() { fontLay->addWidget(m_interfaceFont); fontLay->addSpacing(10); - fontLay->addWidget(new QLabel(tr("Weight *:"))); - fontLay->addWidget(m_interfaceFontWeight); + fontLay->addWidget(new QLabel(tr("Style *:"))); + fontLay->addWidget(m_interfaceFontStyle); fontLay->addStretch(1); } interfaceBottomLay->addLayout(fontLay, 4, 1, 1, 5); @@ -2198,6 +2261,37 @@ PreferencesPopup::PreferencesPopup() loadingBox->setLayout(loadingFrameLay); stackedWidget->addWidget(loadingBox); + //--- Saving -------------------------- + QWidget *savingBox = new QWidget(this); + QVBoxLayout *savingFrameLay = new QVBoxLayout(); + savingFrameLay->setMargin(15); + savingFrameLay->setSpacing(10); + { + QLabel *matteColorLabel = + new QLabel(tr("Matte color is used for background when overwriting " + "raster levels with transparent pixels\nin non " + "alpha-enabled image format."), + this); + savingFrameLay->addWidget(matteColorLabel, 0, Qt::AlignLeft); + + QGridLayout *savingGridLay = new QGridLayout(); + savingGridLay->setVerticalSpacing(10); + savingGridLay->setHorizontalSpacing(15); + savingGridLay->setMargin(0); + { + savingGridLay->addWidget(new QLabel(tr("Matte color: "), this), 0, 0, + Qt::AlignRight); + savingGridLay->addWidget(rasterBackgroundColor, 0, 1, Qt::AlignLeft); + } + savingGridLay->setColumnStretch(0, 0); + savingGridLay->setColumnStretch(1, 1); + savingFrameLay->addLayout(savingGridLay, 0); + + savingFrameLay->addStretch(1); + } + savingBox->setLayout(savingFrameLay); + stackedWidget->addWidget(savingBox); + //--- Import/Export -------------------------- QWidget *ioBox = new QWidget(this); QVBoxLayout *ioLay = new QVBoxLayout(); @@ -2527,6 +2621,8 @@ PreferencesPopup::PreferencesPopup() onionLay->addWidget(m_inksOnly, 0, Qt::AlignLeft | Qt::AlignVCenter); onionLay->addWidget(m_onionSkinDuringPlayback, 0, Qt::AlignLeft | Qt::AlignVCenter); + onionLay->addWidget(m_useOnionColorsForShiftAndTraceCB, 0, + Qt::AlignLeft | Qt::AlignVCenter); QGridLayout *guidedDrawingLay = new QGridLayout(); { guidedDrawingLay->addWidget(new QLabel(tr("Vector Guided Style:")), 0, @@ -2620,6 +2716,23 @@ PreferencesPopup::PreferencesPopup() versionControlBox->setLayout(vcLay); stackedWidget->addWidget(versionControlBox); + //--- Tablet Settings -------------------------- + if (showTabletSettings) { + QWidget *tabletSettingsBox = new QWidget(this); + QVBoxLayout *tsLay = new QVBoxLayout(); + tsLay->setMargin(15); + tsLay->setSpacing(10); + { + tsLay->addWidget(m_enableWinInk, 0, Qt::AlignLeft | Qt::AlignVCenter); + + tsLay->addStretch(1); + + tsLay->addWidget(note_tablet, 0); + } + tabletSettingsBox->setLayout(tsLay); + stackedWidget->addWidget(tabletSettingsBox); + } + mainLayout->addWidget(stackedWidget, 1); } setLayout(mainLayout); @@ -2714,8 +2827,8 @@ PreferencesPopup::PreferencesPopup() this, SLOT(onViewerZoomCenterChanged(int))); ret = ret && connect(m_interfaceFont, SIGNAL(currentIndexChanged(int)), this, SLOT(onInterfaceFontChanged(int))); - ret = ret && connect(m_interfaceFontWeight, SIGNAL(currentIndexChanged(int)), - this, SLOT(onInterfaceFontWeightChanged(int))); + ret = ret && connect(m_interfaceFontStyle, SIGNAL(currentIndexChanged(int)), + this, SLOT(onInterfaceFontStyleChanged(int))); ret = ret && connect(replaceAfterSaveLevelAsCB, SIGNAL(stateChanged(int)), this, SLOT(onReplaceAfterSaveLevelAsChanged(int))); ret = @@ -2771,6 +2884,12 @@ PreferencesPopup::PreferencesPopup() SIGNAL(importPolicyChanged(int)), this, SLOT(onImportPolicyExternallyChanged(int))); + //--- Saving ---------------------- + ret = ret && + connect(rasterBackgroundColor, + SIGNAL(colorChanged(const TPixel32 &, bool)), + SLOT(onRasterBackgroundColorChanged(const TPixel32 &, bool))); + //--- Import/Export ---------------------- ret = ret && connect(m_ffmpegPathFileFld, SIGNAL(pathChanged()), this, SLOT(onFfmpegPathChanged())); @@ -2904,6 +3023,9 @@ PreferencesPopup::PreferencesPopup() SLOT(onOnionSkinVisibilityChanged(int))); ret = ret && connect(m_onionSkinDuringPlayback, SIGNAL(stateChanged(int)), SLOT(onOnionSkinDuringPlaybackChanged(int))); + ret = ret && + connect(m_useOnionColorsForShiftAndTraceCB, SIGNAL(stateChanged(int)), + SLOT(onOnionColorsForShiftAndTraceChanged(int))); ret = ret && connect(m_onionPaperThickness, SIGNAL(editingFinished()), SLOT(onOnionPaperThicknessChanged())); ret = ret && connect(m_guidedDrawingStyle, SIGNAL(currentIndexChanged(int)), @@ -2944,6 +3066,12 @@ PreferencesPopup::PreferencesPopup() SLOT(onAutomaticSVNRefreshChanged(int))); ret = ret && connect(checkForTheLatestVersionCB, SIGNAL(clicked(bool)), SLOT(onCheckLatestVersionChanged(bool))); + + //--- Tablet Settings ---------------------- + if (showTabletSettings) + ret = ret && connect(m_enableWinInk, SIGNAL(stateChanged(int)), + SLOT(onEnableWinInkChanged(int))); + assert(ret); } diff --git a/toonz/sources/toonz/preferencespopup.h b/toonz/sources/toonz/preferencespopup.h index 474e230..02e1d61 100644 --- a/toonz/sources/toonz/preferencespopup.h +++ b/toonz/sources/toonz/preferencespopup.h @@ -16,6 +16,7 @@ // Qt includes #include +#include //============================================================== @@ -55,9 +56,10 @@ private: *m_defLevelType, *m_autocreationType, *m_levelFormatNames, *m_columnIconOm, *m_unitOm, *m_cameraUnitOm, *m_importPolicy, *m_vectorSnappingTargetCB, *m_dropdownShortcutsCycleOptionsCB, - *m_interfaceFont, *m_interfaceFontWeight, *m_guidedDrawingStyle, - *m_functionEditorToggle, *m_cursorBrushType, *m_cursorBrushStyle, - *m_xsheetLayout; + *m_guidedDrawingStyle, *m_functionEditorToggle, *m_cursorBrushType, + *m_cursorBrushStyle, *m_xsheetLayout, *m_interfaceFontStyle; + + QFontComboBox *m_interfaceFont; DVGui::MeasuredDoubleLineEdit *m_defLevelWidth, *m_defLevelHeight; @@ -80,7 +82,8 @@ private: *m_useHigherDpiOnVectorSimplifyCB, *m_keepFillOnVectorSimplifyCB, *m_newLevelToCameraSizeCB, *m_ignoreImageDpiCB, *m_syncLevelRenumberWithXsheet, *m_downArrowInLevelStripCreatesNewFrame, - *m_enableAutoStretch; + *m_enableAutoStretch, *m_enableWinInk, + *m_useOnionColorsForShiftAndTraceCB; DVGui::FileField *m_customProjectRootFileField; @@ -94,6 +97,7 @@ private: private: // QWidget* create(const QString& lbl, bool def, const char* slot); void rebuildFormatsList(); + void rebuilldFontStyleList(); private slots: @@ -179,6 +183,7 @@ private slots: void onReplaceAfterSaveLevelAsChanged(int index); void onOnionSkinVisibilityChanged(int); void onOnionSkinDuringPlaybackChanged(int); + void onOnionColorsForShiftAndTraceChanged(int); void onGuidedDrawingStyleChanged(int); void onActualPixelOnSceneModeChanged(int); void onMultiLayerStylePickerChanged(int); @@ -202,7 +207,7 @@ private slots: void onShortcutCommandsWhileRenamingCellClicked(int); void onWatchFileSystemClicked(int); void onInterfaceFontChanged(int index); - void onInterfaceFontWeightChanged(int index); + void onInterfaceFontStyleChanged(int index); void onXsheetLayoutChanged(int index); void onPathAliasPriorityChanged(int index); void onShowCurrentTimelineChanged(int); @@ -214,6 +219,8 @@ private slots: void onCursorBrushStyleChanged(int index); void onCursorOutlineChanged(int); void onCurrentColumnDataChanged(const TPixel32 &, bool isDragging); + void onEnableWinInkChanged(int index); + void onRasterBackgroundColorChanged(const TPixel32 &, bool isDragging); }; //********************************************************************************** diff --git a/toonz/sources/toonz/previewer.cpp b/toonz/sources/toonz/previewer.cpp index 5ee810c..264f959 100644 --- a/toonz/sources/toonz/previewer.cpp +++ b/toonz/sources/toonz/previewer.cpp @@ -39,7 +39,6 @@ #include "toonz/toonzscene.h" #include "toonz/txshlevel.h" #include "toonz/txsheet.h" -#include "toonz/sceneproperties.h" #include "toonz/tcamera.h" #include "toonz/palettecontroller.h" diff --git a/toonz/sources/toonz/rendercommand.cpp b/toonz/sources/toonz/rendercommand.cpp index 85e7925..8424092 100644 --- a/toonz/sources/toonz/rendercommand.cpp +++ b/toonz/sources/toonz/rendercommand.cpp @@ -512,13 +512,16 @@ void RenderCommand::rasterRender(bool isPreview) { TPixel32 currBgColor = scene->getProperties()->getBgColor(); m_priorBgColor = currBgColor; - // fixes background colors for non alpha-enabled export types (eventually + // fixes background colors for non alpha-enabled movie types (eventually // transparent gif would be good) - if (ext == "jpg" || ext == "avi" || ext == "bmp" || ext == "mp4" || - ext == "webm" || ext == "gif") { - currBgColor.m = 255; + currBgColor.m = 255; + if (isMovieType(ext)) { scene->getProperties()->setBgColor(currBgColor); } + // for non alpha-enabled images (like jpg), background color will be inserted + // in TImageWriter::save() (see timage_io.cpp) + else + TImageWriter::setBackgroundColor(currBgColor); // Extract output properties TOutputProperties *prop = isPreview @@ -618,6 +621,10 @@ TPixel32 RenderCommand::m_priorBgColor; void RenderCommand::resetBgColor() { ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); scene->getProperties()->setBgColor(m_priorBgColor); + + // revert background color settings + TImageWriter::setBackgroundColor( + Preferences::instance()->getRasterBackgroundColor()); } //=================================================================== diff --git a/toonz/sources/toonz/ruler.cpp b/toonz/sources/toonz/ruler.cpp index e736c15..c6d9d50 100644 --- a/toonz/sources/toonz/ruler.cpp +++ b/toonz/sources/toonz/ruler.cpp @@ -272,7 +272,7 @@ void Ruler::mousePressEvent(QMouseEvent *e) { // aggiorna sprop!!!! } else { // muove la guida vecchia - if (selected < count - 1) tswap(guides[selected], guides.back()); + if (selected < count - 1) std::swap(guides[selected], guides.back()); // aggiorna sprop!!!! } m_moving = true; diff --git a/toonz/sources/toonz/runscriptcommand.cpp b/toonz/sources/toonz/runscriptcommand.cpp index e32b189..7a7ea86 100644 --- a/toonz/sources/toonz/runscriptcommand.cpp +++ b/toonz/sources/toonz/runscriptcommand.cpp @@ -10,7 +10,6 @@ #include "toonz/toonzscene.h" #include "toonz/toonzfolders.h" #include "filebrowserpopup.h" -#include "toonz/tproject.h" #include "floatingpanelcommand.h" #include "scriptconsolepanel.h" #include "tsystem.h" diff --git a/toonz/sources/toonz/scanlist.cpp b/toonz/sources/toonz/scanlist.cpp index fda6ada..fe14867 100644 --- a/toonz/sources/toonz/scanlist.cpp +++ b/toonz/sources/toonz/scanlist.cpp @@ -49,8 +49,8 @@ ScanListFrame::ScanListFrame(const ScanListFrame &src) ScanListFrame &ScanListFrame::operator=(const ScanListFrame &src) { ScanListFrame tmp(*this); - tswap(m_xl, tmp.m_xl); - tswap(m_fid, tmp.m_fid); + std::swap(m_xl, tmp.m_xl); + std::swap(m_fid, tmp.m_fid); return *this; } diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp index 0cd90ed..4ff0e27 100644 --- a/toonz/sources/toonz/sceneviewer.cpp +++ b/toonz/sources/toonz/sceneviewer.cpp @@ -56,7 +56,6 @@ #include "toonz/cleanupparameters.h" #include "toonz/toonzimageutils.h" #include "toonz/txshleveltypes.h" -#include "toonz/preferences.h" #include "subcameramanager.h" // TnzCore includes @@ -391,10 +390,9 @@ public: if (std::string(m_cmdId) == MI_ShiftTrace) { cm->enable(MI_EditShift, checked); cm->enable(MI_NoShift, checked); - if (!checked) { - cm->setChecked(MI_EditShift, false); - } + if (checked) OnioniSkinMaskGUI::resetShiftTraceFrameOffset(); // cm->getAction(MI_NoShift)->setChecked(false); + TApp::instance()->getCurrentOnionSkin()->notifyOnionSkinMaskChanged(); } else if (std::string(m_cmdId) == MI_EditShift) { if (checked) { QAction *noShiftAction = @@ -427,6 +425,7 @@ public: OnionSkinMask osm = TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask(); osm.setShiftTraceStatus(status); + osm.clearGhostFlipKey(); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(osm); } @@ -782,6 +781,8 @@ void SceneViewer::showEvent(QShowEvent *) { m_shownOnce = true; } TApp::instance()->setActiveViewer(this); + + update(); } //----------------------------------------------------------------------------- @@ -1607,6 +1608,13 @@ void SceneViewer::drawScene() { drawSpline(getViewMatrix(), clipRect, m_referenceMode == CAMERA3D_REFERENCE, m_pixelSize); assert(glGetError() == 0); + + // gather animated guide strokes' bounding boxes + // it is used for updating viewer next time + std::vector guidedStrokes = painter.getGuidedStrokes(); + for (auto itr = guidedStrokes.begin(); itr != guidedStrokes.end(); ++itr) { + m_guidedDrawingBBox += (*itr)->getBBox(); + } } } @@ -1748,11 +1756,19 @@ void SceneViewer::GLInvalidateRect(const TRectD &rect) { return; else if (rect.isEmpty()) m_clipRect = InvalidateAllRect; - else + else { m_clipRect += rect; + if (!m_guidedDrawingBBox.isEmpty()) { + TTool *tool = TApp::instance()->getCurrentTool()->getTool(); + TPointD topLeft = tool->getMatrix() * m_guidedDrawingBBox.getP00(); + TPointD bottomRight = tool->getMatrix() * m_guidedDrawingBBox.getP11(); + m_clipRect += TRectD(topLeft, bottomRight); + } + } update(); if (m_vRuler) m_vRuler->update(); if (m_hRuler) m_hRuler->update(); + m_guidedDrawingBBox.empty(); } //----------------------------------------------------------------------------- @@ -2172,6 +2188,7 @@ void SceneViewer::onLevelChanged() { * for Ink&Paint work properly */ void SceneViewer::onLevelSwitched() { + invalidateToolStatus(); TApp *app = TApp::instance(); TTool *tool = app->getCurrentTool()->getTool(); TXshLevel *level = app->getCurrentLevel()->getLevel(); @@ -2376,31 +2393,39 @@ includeInvisible); //----------------------------------------------------------------------------- int SceneViewer::posToRow(const TPointD &p, double distance, - bool includeInvisible) const { - int oldRasterizePli = TXshSimpleLevel::m_rasterizePli; - TApp *app = TApp::instance(); - ToonzScene *scene = app->getCurrentScene()->getScene(); - TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); - int frame = app->getCurrentFrame()->getFrame(); - int currentColumnIndex = app->getCurrentColumn()->getColumnIndex(); - OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask(); + bool includeInvisible, bool currentColumnOnly) const { + int oldRasterizePli = TXshSimpleLevel::m_rasterizePli; + TApp *app = TApp::instance(); + OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask(); TPointD pos = TPointD(p.x - width() / 2, p.y - height() / 2); Stage::Picker picker(getViewMatrix(), pos, m_visualSettings); picker.setDistance(distance); - TXshSimpleLevel::m_rasterizePli = 0; + if (app->getCurrentFrame()->isEditingLevel()) { + Stage::visit(picker, app->getCurrentLevel()->getLevel(), + app->getCurrentFrame()->getFid(), osm, + app->getCurrentFrame()->isPlaying(), false); + } else { + ToonzScene *scene = app->getCurrentScene()->getScene(); + TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); + int frame = app->getCurrentFrame()->getFrame(); + int currentColumnIndex = app->getCurrentColumn()->getColumnIndex(); - Stage::VisitArgs args; - args.m_scene = scene; - args.m_xsh = xsh; - args.m_row = frame; - args.m_col = currentColumnIndex; - args.m_osm = &osm; - args.m_onlyVisible = includeInvisible; + TXshSimpleLevel::m_rasterizePli = 0; + + Stage::VisitArgs args; + args.m_scene = scene; + args.m_xsh = xsh; + args.m_row = frame; + args.m_col = currentColumnIndex; + args.m_osm = &osm; + args.m_onlyVisible = includeInvisible; - Stage::visit(picker, args); + if (currentColumnOnly) picker.setCurrentColumnIndex(currentColumnIndex); + Stage::visit(picker, args); + } TXshSimpleLevel::m_rasterizePli = oldRasterizePli; return picker.getRow(); } diff --git a/toonz/sources/toonz/sceneviewer.h b/toonz/sources/toonz/sceneviewer.h index 05c6a47..d6139f1 100644 --- a/toonz/sources/toonz/sceneviewer.h +++ b/toonz/sources/toonz/sceneviewer.h @@ -73,12 +73,13 @@ class SceneViewer final : public GLWidgetForHighDpi, bool m_tabletEvent, m_tabletMove; enum TabletState { None = 0, - Touched, + Touched, // Pressed for mouse StartStroke, // this state is to detect the first call // of TabletMove just after TabletPress OnStroke, Released - } m_tabletState = None; + } m_tabletState = None, + m_mouseState = None; // used to handle wrong mouse drag events! bool m_buttonClicked, m_toolSwitched; bool m_shownOnce = false; @@ -173,6 +174,10 @@ class SceneViewer final : public GLWidgetForHighDpi, // So discarding the resources in old context in initializeGL. TGlContext m_currentContext; + // used for updating viewer where the animated guide appears + // updated in drawScene() and used in GLInvalidateRect() + TRectD m_guidedDrawingBBox; + public: enum ReferenceMode { NORMAL_REFERENCE = 1, @@ -370,8 +375,8 @@ protected: //! return the row of the drawings intersecting point \b p (used with onion //! skins) //! (window coordinate, pixels, bottom-left origin) - int posToRow(const TPointD &p, double distance, - bool includeInvisible = true) const override; + int posToRow(const TPointD &p, double distance, bool includeInvisible = true, + bool currentColumnOnly = false) const override; void dragEnterEvent(QDragEnterEvent *event) override; void dropEvent(QDropEvent *event) override; diff --git a/toonz/sources/toonz/sceneviewerevents.cpp b/toonz/sources/toonz/sceneviewerevents.cpp index e6d82b6..2817f18 100644 --- a/toonz/sources/toonz/sceneviewerevents.cpp +++ b/toonz/sources/toonz/sceneviewerevents.cpp @@ -271,10 +271,15 @@ void SceneViewer::tabletEvent(QTabletEvent *e) { // So, in such case set m_tabletEvent = FALSE and let the mousePressEvent to // work. if (e->button() == Qt::LeftButton) { - TMouseEvent mouseEvent; - initToonzEvent(mouseEvent, e, height(), m_pressure, getDevPixRatio()); - m_tabletState = Touched; - onPress(mouseEvent); + // Proces the 1st tabletPress encountered and ignore back-to-back + // tabletPress events. Treat it as if it happened so a following + // mousePressEvent gets ignored + if (m_tabletState == Released || m_tabletState == None) { + TMouseEvent mouseEvent; + initToonzEvent(mouseEvent, e, height(), m_pressure, getDevPixRatio()); + m_tabletState = Touched; + onPress(mouseEvent); + } } else m_tabletEvent = false; #endif @@ -365,6 +370,11 @@ void SceneViewer::onLeave() { if (m_freezedStatus != NO_FREEZED) return; TTool *tool = TApp::instance()->getCurrentTool()->getTool(); if (tool && tool->isEnabled()) tool->onLeave(); + + // force reset the flipping of shift & trace + if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked()) + TTool::getTool("T_ShiftTrace", TTool::ToonzImage)->onLeave(); + update(); } @@ -542,6 +552,7 @@ void SceneViewer::onMove(const TMouseEvent &event) { // sometimes the mousePressedEvent is postponed to a wrong mouse move // event! if (m_buttonClicked && !m_toolSwitched) tool->leftButtonDrag(pos, event); + m_mouseState = OnStroke; } else if (m_pressure == 0.0) { tool->mouseMove(pos, event); } @@ -588,6 +599,7 @@ void SceneViewer::mousePressEvent(QMouseEvent *event) { // and will cancel the onPress operation called here. TMouseEvent mouseEvent; + m_mouseState = Touched; initToonzEvent(mouseEvent, event, height(), 1.0, getDevPixRatio()); onPress(mouseEvent); } @@ -596,11 +608,20 @@ void SceneViewer::mousePressEvent(QMouseEvent *event) { void SceneViewer::onPress(const TMouseEvent &event) { if (m_mouseButton != Qt::NoButton) { - // if some button is pressed while another button being active, - // finish the action for the previous button first. - TMouseEvent preEvent = event; - preEvent.m_button = m_mouseButton; - onRelease(preEvent); + if (event.m_isTablet && m_mouseState != None) { + // qDebug() << "[onPress] Switched from MousePress to TabletPress"; + // TabletPress came immediately after MousePress. Let's switch to + // tabletPress but not end the prior action or it leaves an extra + // stroke + m_mouseState = None; + m_buttonClicked = false; + } else { + // if some button is pressed while another button being active, + // finish the action for the previous button first. + TMouseEvent preEvent = event; + preEvent.m_button = m_mouseButton; + onRelease(preEvent); + } } // evita i press ripetuti @@ -632,6 +653,7 @@ void SceneViewer::onPress(const TMouseEvent &event) { m_compareSettings.m_compareY = ImagePainter::DefaultCompareValue; update(); m_tabletEvent = false; + m_tabletState = None; return; } else if (abs((height() - m_pos.y()) - height() * m_compareSettings.m_compareY) < 20) { @@ -640,6 +662,7 @@ void SceneViewer::onPress(const TMouseEvent &event) { m_compareSettings.m_compareX = ImagePainter::DefaultCompareValue; update(); m_tabletEvent = false; + m_tabletState = None; return; } else m_compareSettings.m_dragCompareX = m_compareSettings.m_dragCompareY = @@ -651,6 +674,7 @@ void SceneViewer::onPress(const TMouseEvent &event) { TTool *tool = TApp::instance()->getCurrentTool()->getTool(); if (!tool || !tool->isEnabled()) { m_tabletEvent = false; + m_tabletState = None; return; } tool->setViewer(this); @@ -658,6 +682,7 @@ void SceneViewer::onPress(const TMouseEvent &event) { tool = TApp::instance()->getCurrentTool()->getTool(); if (!tool || !tool->isEnabled()) { m_tabletEvent = false; + m_tabletState = None; return; } tool->setViewer(this); @@ -678,6 +703,7 @@ void SceneViewer::onPress(const TMouseEvent &event) { m_tabletState = StartStroke; tool->leftButtonDown(pos, event); } else if (m_mouseButton == Qt::LeftButton) { + m_mouseState = StartStroke; TApp::instance()->getCurrentTool()->setToolBusy(true); tool->leftButtonDown(pos, event); } @@ -708,6 +734,7 @@ void SceneViewer::mouseReleaseEvent(QMouseEvent *event) { } TMouseEvent mouseEvent; + if (m_mouseState != None) m_mouseState = Released; initToonzEvent(mouseEvent, event, height(), 1.0, getDevPixRatio()); onRelease(mouseEvent); } @@ -779,6 +806,7 @@ quit: // Don't clear it out table state so the tablePress event will process // correctly. if (m_tabletState != Touched) m_tabletState = None; + m_mouseState = None; m_tabletMove = false; m_pressure = 0; // Leave m_tabletEvent as-is in order to check whether the onRelease is called @@ -963,6 +991,8 @@ void SceneViewer::gestureEvent(QGestureEvent *e) { void SceneViewer::touchEvent(QTouchEvent *e, int type) { if (type == QEvent::TouchBegin) { + if (m_tabletEvent) return; + m_touchActive = true; m_firstPanPoint = e->touchPoints().at(0).pos(); m_undoPoint = m_firstPanPoint; @@ -1012,19 +1042,83 @@ void SceneViewer::touchEvent(QTouchEvent *e, int type) { //----------------------------------------------------------------------------- bool SceneViewer::event(QEvent *e) { - if (CommandManager::instance() + /* + switch (e->type()) { + // case QEvent::Enter: + // qDebug() << "[enter] ************************** Enter"; + // break; + // case QEvent::Leave: + // qDebug() << "[enter] ************************** Leave"; + // break; + + case QEvent::TabletPress: { + QTabletEvent *te = static_cast(e); + qDebug() << "[enter] ************************** TabletPress mouseState(" + << m_mouseState << ") tabletState(" << m_tabletState + << ") pressure(" << m_pressure << ") pointerType(" + << te->pointerType() << ") device(" << te->device() << ")"; + } break; + // case QEvent::TabletMove: + // qDebug() << "[enter] ************************** TabletMove + //mouseState("<type() == QEvent::Gesture && + CommandManager::instance() ->getAction(MI_TouchGestureControl) ->isChecked()) { - if (e->type() == QEvent::Gesture) { - gestureEvent(static_cast(e)); - return true; - } - if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchEnd || - e->type() == QEvent::TouchCancel || e->type() == QEvent::TouchUpdate) { - touchEvent(static_cast(e), e->type()); - m_gestureActive = true; - return true; - } + gestureEvent(static_cast(e)); + return true; + } + if ((e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchEnd || + e->type() == QEvent::TouchCancel || e->type() == QEvent::TouchUpdate) && + CommandManager::instance() + ->getAction(MI_TouchGestureControl) + ->isChecked()) { + touchEvent(static_cast(e), e->type()); + m_gestureActive = true; + return true; } if (e->type() == QEvent::ShortcutOverride || e->type() == QEvent::KeyPress) { if (!((QKeyEvent *)e)->isAutoRepeat()) { @@ -1041,6 +1135,16 @@ bool SceneViewer::event(QEvent *e) { else if (tool && tool->isEventAcceptable(e)) { e->accept(); } + // if the Shift & Trace mode is active, then override F1, F2 and F3 key + // actions by flipping feature + else if (CommandManager::instance() + ->getAction(MI_ShiftTrace) + ->isChecked() && + TTool::getTool("T_ShiftTrace", TTool::ToonzImage) + ->isEventAcceptable(e)) { + e->accept(); + } + return true; } if (e->type() == QEvent::KeyRelease) { @@ -1064,44 +1168,6 @@ bool SceneViewer::event(QEvent *e) { clock.start(); } - /* - switch(e->type()) - { - case QEvent::Enter: - qDebug() << "************************** Enter"; - break; - case QEvent::Leave: - qDebug() << "************************** Leave"; - break; - - case QEvent::TabletPress: - qDebug() << "************************** TabletPress" << m_pressure; - break; - case QEvent::TabletMove: - qDebug() << "************************** TabletMove"; - break; - case QEvent::TabletRelease: - qDebug() << "************************** TabletRelease"; - break; - - - case QEvent::MouseButtonPress: - qDebug() << "**************************MouseButtonPress" << m_pressure << " " - << m_tabletEvent; - break; - case QEvent::MouseMove: - qDebug() << "**************************MouseMove" << m_pressure; - break; - case QEvent::MouseButtonRelease: - qDebug() << "**************************MouseButtonRelease"; - break; - - case QEvent::MouseButtonDblClick: - qDebug() << "============================== MouseButtonDblClick"; - break; - } - */ - return QOpenGLWidget::event(e); } @@ -1213,6 +1279,18 @@ void SceneViewer::keyPressEvent(QKeyEvent *event) { event->ignore(); return true; } + // pressing F1, F2 or F3 key will flip between corresponding ghost + if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked() && + (Qt::Key_F1 <= key && key <= Qt::Key_F3)) { + OnionSkinMask osm = + TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask(); + if (osm.getGhostFlipKey() != key) { + osm.appendGhostFlipKey(key); + TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(osm); + TApp::instance()->getCurrentOnionSkin()->notifyOnionSkinMaskChanged(); + } + return true; + } } if (!tool->isEnabled()) return false; @@ -1311,6 +1389,15 @@ void SceneViewer::keyReleaseEvent(QKeyEvent *event) { setToolCursor(this, tool->getCursorId()); } + if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked() && + (Qt::Key_F1 <= key && key <= Qt::Key_F3)) { + OnionSkinMask osm = + TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask(); + osm.removeGhostFlipKey(key); + TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(osm); + TApp::instance()->getCurrentOnionSkin()->notifyOnionSkinMaskChanged(); + } + if (tool->getName() == T_Type) event->accept(); else @@ -1397,8 +1484,8 @@ void SceneViewer::onContextMenu(const QPoint &pos, const QPoint &globalPos) { menu->addLevelCommands(columnIndices); - ComboViewerPanel *cvp = qobject_cast( - parentWidget()->parentWidget()->parentWidget()); + ComboViewerPanel *cvp = + qobject_cast(parentWidget()->parentWidget()); if (cvp) { menu->addSeparator(); cvp->addShowHideContextMenu(menu); diff --git a/toonz/sources/toonz/scriptconsolepanel.cpp b/toonz/sources/toonz/scriptconsolepanel.cpp index a18c37c..7c34cdc 100644 --- a/toonz/sources/toonz/scriptconsolepanel.cpp +++ b/toonz/sources/toonz/scriptconsolepanel.cpp @@ -15,7 +15,6 @@ #include "toonz/txshsimplelevel.h" #include "toonzqt/selection.h" #include "toonzqt/tselectionhandle.h" -#include "tapp.h" #include "flipbook.h" #include "tvectorimage.h" diff --git a/toonz/sources/toonz/separatecolorspopup.cpp b/toonz/sources/toonz/separatecolorspopup.cpp new file mode 100644 index 0000000..da8c13d --- /dev/null +++ b/toonz/sources/toonz/separatecolorspopup.cpp @@ -0,0 +1,1748 @@ +#include "separatecolorspopup.h" + +#include "separatecolorsswatch.h" + +#include "menubarcommandids.h" +#include "tapp.h" +#include "tlevel_io.h" +#include "tiio.h" +#include "toutputproperties.h" +#include "filebrowser.h" + +#include "toonzqt/gutil.h" +#include "toonzqt/imageutils.h" +#include "toonzqt/menubarcommand.h" +#include "toonzqt/filefield.h" +#include "toonzqt/intfield.h" +#include "toonzqt/colorfield.h" +#include "toonzqt/checkbox.h" +#include "toonzqt/doublefield.h" +#include "toonz/tscenehandle.h" +#include "toonz/toonzscene.h" +#include "toonz/sceneproperties.h" +#include "tsystem.h" +#include "tenv.h" +#include "tpixelutils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TEnv::StringVar SeparateColorsPopup_PaperColor("SeparateColorsPopup_PaperColor", + "#FFFFFF"); +TEnv::StringVar SeparateColorsPopup_MainColor("SeparateColorsPopup_MainColor", + "#000000"); +TEnv::StringVar SeparateColorsPopup_SubColor1("SeparateColorsPopup_SubColor1", + "#FF0000"); +TEnv::StringVar SeparateColorsPopup_SubColor2("SeparateColorsPopup_SubColor2", + "#0000FF"); +TEnv::StringVar SeparateColorsPopup_SubColor3("SeparateColorsPopup_SubColor3", + "#00FF00"); + +TEnv::DoubleVar SeparateColorsPopup_SubAdjust("SeparateColorsPopup_SubAdjust", + 3.0); +TEnv::DoubleVar SeparateColorsPopup_BorderSmooth( + "SeparateColorsPopup_BorderSmooth", 0.1); +TEnv::IntVar SeparateColorsPopup_OutMain("SeparateColorsPopup_OutMain", 1); +TEnv::IntVar SeparateColorsPopup_OutSub1("SeparateColorsPopup_OutSub1", 1); +TEnv::IntVar SeparateColorsPopup_OutSub2("SeparateColorsPopup_OutSub2", 1); +TEnv::IntVar SeparateColorsPopup_OutSub3("SeparateColorsPopup_OutSub3", 0); +TEnv::StringVar SeparateColorsPopup_MainSuffix("SeparateColorsPopup_MainSuffix", + "_m"); +TEnv::StringVar SeparateColorsPopup_Sub1Suffix("SeparateColorsPopup_Sub1Suffix", + "_s1"); +TEnv::StringVar SeparateColorsPopup_Sub2Suffix("SeparateColorsPopup_Sub2Suffix", + "_s2"); +TEnv::StringVar SeparateColorsPopup_Sub3Suffix("SeparateColorsPopup_Sub3Suffix", + "_s3"); + +TEnv::IntVar SeparateColorsPopup_doMatte("SeparateColorsPopup_DoMatte", 1); +TEnv::DoubleVar SeparateColorsPopup_MatteThreshold( + "SeparateColorsPopup_MatteThreshold ", 0.0); +TEnv::IntVar SeparateColorsPopup_MatteRadius("SeparateColorsPopup_MatteRadius", + 0); + +TEnv::StringVar SeparateColorsPopup_FileFormat("SeparateColorsPopup_FileFormat", + "png"); + +//============================================================================= +// SeparateColorsPopup +//----------------------------------------------------------------------------- + +namespace { +//-------------------------------------------------------------------- +void getFrameIds(int from, int to, const TLevelP& level, + std::vector& frames) { + std::string msg; + int r0, r1; + TLevel::Iterator begin = level->begin(); + TLevel::Iterator end = level->end(); + end--; + + r0 = from; + r1 = to; + if (r0 > r1) { + int app = r0; + r0 = r1; + r1 = app; + } + TLevel::Iterator it = begin; + if (r0 != -1 && r0 <= level->getFrameCount()) std::advance(it, r0 - 1); + while (it != level->end() && r1 >= r0) { + frames.push_back(it->first); + if (r0 != -1) ++r0; + ++it; + } +} + +struct uchar3 { + unsigned char x, y, z; +}; +struct uchar4 { + unsigned char x, y, z, w; +}; + +// returns the factors of the equation of a plane which touches the specified 3 +// points +// a * x + b * y + c * z = d -> returns (a,b,c,d) +QVector4D getPane(QVector3D p0, QVector3D p1, QVector3D p2) { + // vector p0->p1 + QVector3D vec_p01 = p1 - p0; + // vector p0->p2 + QVector3D vec_p02 = p2 - p0; + + // cross product + QVector3D cross_p01_p02 = QVector3D::crossProduct(vec_p01, vec_p02); + + QVector4D pane(cross_p01_p02.x(), cross_p01_p02.y(), cross_p01_p02.z(), + cross_p01_p02.x() * p0.x() + cross_p01_p02.y() * p0.y() + + cross_p01_p02.z() * p0.z()); + return pane; +} + +QVector3D myPix2Rgb(TPixel32 pix) { + return QVector3D((float)pix.r / (float)TPixel32::maxChannelValue, + (float)pix.g / (float)TPixel32::maxChannelValue, + (float)pix.b / (float)TPixel32::maxChannelValue); +} + +QVector3D myRgb2Hls(QVector3D rgb) { + double h, l, s; + rgb2hls(rgb.x(), rgb.y(), rgb.z(), &h, &l, &s); + return QVector3D((float)h, (float)l, (float)s); +} + +QVector3D myHls2Xyz(QVector3D hls) { + float hueRad = hls.x() * 3.14159265f / 180.0f; + return QVector3D( + hls.z() * std::cos(hueRad) * (1.0f - (std::abs(hls.y() - 0.5f) * 2.0f)), + hls.y() - 0.5f, + hls.z() * std::sin(hueRad) * (1.0f - (std::abs(hls.y() - 0.5f) * 2.0f))); +} + +// modify values +float modify(float val) { + if (val >= 0.5f) return 1.0f; + + return val * 2.0f; +} + +// separate main color and two sub colors +QVector3D separate3_Kernel(QVector3D pix_xyz, QVector3D paper_xyz, + QVector3D main_xyz, QVector3D sub1_xyz, + QVector3D sub2_xyz, QVector4D pane, float mainAdjust, + float borderRatio) { + // vector paper -> pixel + QVector3D vec_e = pix_xyz - paper_xyz; + + float de = pane.x() * vec_e.x() + pane.y() * vec_e.y() + pane.z() * vec_e.z(); + + // if de == 0, vec_e is in pallarel with the pane + if (de == 0.0f) return QVector3D(0.0f, 0.0f, 0.0f); + + // compute the factor t which extends vec_e to the pane + float t = (pane.w() - (pane.x() * paper_xyz.x() + pane.y() * paper_xyz.y() + + pane.z() * paper_xyz.z())) / + de; + + // intersecting point on the pane + QVector3D Q = paper_xyz + t * vec_e; + + // ratio_ms1 + // vector main color -> Q + QVector3D vec_mQ = Q - main_xyz; + // vector main color -> sub1 color + QVector3D vec_ms1 = sub1_xyz - main_xyz; + float ratio_ms1 = + QVector3D::dotProduct(vec_mQ, vec_ms1) / vec_ms1.lengthSquared(); + + // value_ms1 + float value_ms1; + if (ratio_ms1 <= 1.0f / (1.0f + mainAdjust) - borderRatio) + value_ms1 = 1.0f; + else if (ratio_ms1 < 1.0f / (1.0f + mainAdjust) + borderRatio) + value_ms1 = 1.0f - + (ratio_ms1 - 1.0f / (1.0f + mainAdjust) + borderRatio) / + (2.0f * borderRatio); + else + value_ms1 = 0.0f; + + // ratio_ms2 + // vector main color -> sub2 color + QVector3D vec_ms2 = sub2_xyz - main_xyz; + float ratio_ms2 = + QVector3D::dotProduct(vec_mQ, vec_ms2) / vec_ms2.lengthSquared(); + + // value_ms2 + float value_ms2; + if (ratio_ms2 <= 1.0f / (1.0f + mainAdjust) - borderRatio) + value_ms2 = 1.0f; + else if (ratio_ms2 < 1.0f / (1.0f + mainAdjust) + borderRatio) + value_ms2 = 1.0f - + (ratio_ms2 - 1.0f / (1.0f + mainAdjust) + borderRatio) / + (2.0f * borderRatio); + else + value_ms2 = 0.0f; + + // ratio_s1s2 + // vector sub1 color -> Q + QVector3D vec_s1Q = Q - sub1_xyz; + // vector sub1 color -> sub2 color + QVector3D vec_s1s2 = sub2_xyz - sub1_xyz; + float ratio_s1s2 = + QVector3D::dotProduct(vec_s1Q, vec_s1s2) / vec_s1s2.lengthSquared(); + + // value_s1s2 + float value_s1s2; + if (ratio_s1s2 <= 0.5f - borderRatio) + value_s1s2 = 1.0f; + else if (ratio_s1s2 < 0.5f + borderRatio) + value_s1s2 = + 1.0f - (ratio_s1s2 - 0.5f + borderRatio) / (2.0f * borderRatio); + else + value_s1s2 = 0.0f; + + float base_m = modify(value_ms1) * modify(value_ms2); + float base_s1 = modify(1.0f - value_ms1) * modify(value_s1s2); + float base_s2 = modify(1.0f - value_ms2) * modify(1.0f - value_s1s2); + + // vector paper color -> main color + QVector3D vec_pm = main_xyz - paper_xyz; + // vector paper color -> sub1 color + QVector3D vec_ps1 = sub1_xyz - paper_xyz; + // vector paper color -> sub2 color + QVector3D vec_ps2 = sub2_xyz - paper_xyz; + + float ratio_m = QVector3D::dotProduct(vec_e, vec_pm) / vec_pm.lengthSquared(); + float ratio_s1 = + QVector3D::dotProduct(vec_e, vec_ps1) / vec_ps1.lengthSquared(); + float ratio_s2 = + QVector3D::dotProduct(vec_e, vec_ps2) / vec_ps2.lengthSquared(); + + return QVector3D(std::max(0.0f, base_m * ratio_m), + std::max(0.0f, base_s1 * ratio_s1), + std::max(0.0f, base_s2 * ratio_s2)); +} + +// compute intensity of each pencil color +// main = out.x(), sub1 = out.y(), sub2 = out.z() +void separate3Colors(int i, QVector3D* src, QVector3D* out, QVector3D paper_xyz, + QVector3D main_xyz, QVector3D sub1_xyz, QVector3D sub2_xyz, + QVector4D pane, float mainAdjust, float borderRatio) { + // compute HLS value of the target pixel + // then convert HLS value to XYZ coordinate + QVector3D pix_xyz = myHls2Xyz(myRgb2Hls(src[i])); + + // pixels lighter than the paper color is 100% paper + if (pix_xyz.y() >= paper_xyz.y()) { + out[i].setX(0.0f); + out[i].setY(0.0f); + out[i].setZ(0.0f); + return; + } + + out[i] = separate3_Kernel(pix_xyz, paper_xyz, main_xyz, sub1_xyz, sub2_xyz, + pane, mainAdjust, borderRatio); +} + +QVector2D getFactor(QVector3D vec, QVector3D point1, QVector3D point2) { + float b = (point1.x() * vec.y() - point1.y() * vec.x()) / + (point1.x() * point2.y() - point2.x() * point1.y()); + float a = (vec.x() - b * point2.x()) / point1.x(); + + return QVector2D(a, b); +} + +// compute intensity of each pencil color +// main = out.x(), sub1 = out.y(), sub2 = out.z(), sub3 = out.w() +void separate4Colors(int i, QVector3D* src, QVector4D* out, QVector3D paper_xyz, + QVector3D main_xyz, QVector3D sub1_xyz, QVector3D sub2_xyz, + QVector3D sub3_xyz, QVector4D pane_m12, QVector4D pane_m13, + QVector4D pane_m23, QVector4D pane_123, + QVector3D R, // intersection of paper->main vector and + // plane of 3 sub colors + float mainAdjust, float borderRatio) { + // compute HLS value of the target pixel + // then convert HLS value to XYZ coordinate + QVector3D pix_xyz = myHls2Xyz(myRgb2Hls(src[i])); + + // pixels lighter than the paper color is 100% paper + if (pix_xyz.y() >= paper_xyz.y()) { + out[i].setX(0.0f); + out[i].setY(0.0f); + out[i].setZ(0.0f); + out[i].setW(0.0f); + return; + } + + // vector paper -> pixel + QVector3D vec_e = pix_xyz - paper_xyz; + + float de = pane_123.x() * vec_e.x() + pane_123.y() * vec_e.y() + + pane_123.z() * vec_e.z(); + + // if de == 0, vec_e is in pallarel with the pane + if (de == 0.0f) { + out[i].setX(0.0f); + out[i].setY(0.0f); + out[i].setZ(0.0f); + out[i].setW(0.0f); + return; + } + + // compute the factor t which extends vec_e to the pane + float t = (pane_123.w() - + (pane_123.x() * paper_xyz.x() + pane_123.y() * paper_xyz.y() + + pane_123.z() * paper_xyz.z())) / + de; + + // intersecting point on the pane + QVector3D Q = paper_xyz + t * vec_e; + + // vector R (pencil on the pane) -> Q (current pixel on the pane) + QVector3D vec_RQ = Q - R; + + // vector from R to each sub color + QVector3D vec_RS1 = sub1_xyz - R; + QVector3D vec_RS2 = sub2_xyz - R; + QVector3D vec_RS3 = sub3_xyz - R; + + // define which two sub colors are mixed in this pixel. + // obtain factors + QVector2D k_S1S2 = getFactor(vec_RQ, vec_RS1, vec_RS2); + + // in case of sub1 and sub2. sub3 is 0 + if (k_S1S2.x() >= 0.0f && k_S1S2.y() >= 0.0f) { + QVector3D ret = + separate3_Kernel(pix_xyz, paper_xyz, main_xyz, sub1_xyz, sub2_xyz, + pane_m12, mainAdjust, borderRatio); + + out[i].setX(ret.x()); + out[i].setY(ret.y()); + out[i].setZ(ret.z()); + out[i].setW(0.0f); + } else { + QVector2D k_S1S3 = getFactor(vec_RQ, vec_RS1, vec_RS3); + // in case of sub1 and sub3. sub2 is 0 + if (k_S1S3.x() >= 0.0f && k_S1S3.y() >= 0.0f) { + QVector3D ret = + separate3_Kernel(pix_xyz, paper_xyz, main_xyz, sub1_xyz, sub3_xyz, + pane_m13, mainAdjust, borderRatio); + + out[i].setX(ret.x()); + out[i].setY(ret.y()); + out[i].setZ(0.0f); + out[i].setW(ret.z()); + } + // in case of sub2 and sub3. sub1 is 0 + else { + QVector3D ret = + separate3_Kernel(pix_xyz, paper_xyz, main_xyz, sub2_xyz, sub3_xyz, + pane_m23, mainAdjust, borderRatio); + + out[i].setX(ret.x()); + out[i].setY(0.0f); + out[i].setZ(ret.y()); + out[i].setW(ret.z()); + } + } +} + +void maskByThres(int i, QVector3D* out, uchar3* mask, float maskThres) { + if (out[i].x() < maskThres) + mask[i].x = 0; + else + mask[i].x = 1; + + if (out[i].y() < maskThres) + mask[i].y = 0; + else + mask[i].y = 1; + + if (out[i].z() < maskThres) + mask[i].z = 0; + else + mask[i].z = 1; +} + +void maskByThres(int i, QVector4D* out, uchar4* mask, float maskThres) { + if (out[i].x() < maskThres) + mask[i].x = 0; + else + mask[i].x = 1; + + if (out[i].y() < maskThres) + mask[i].y = 0; + else + mask[i].y = 1; + + if (out[i].z() < maskThres) + mask[i].z = 0; + else + mask[i].z = 1; + + if (out[i].w() < maskThres) + mask[i].w = 0; + else + mask[i].w = 1; +} + +void expandMask(int x, int y, uchar3* mask_host, int lx, int ly, int gen) { + int i = y * lx + x; + // check if the target pixel is already opac + bool foundMain = (mask_host[i].x >= 1 && mask_host[i].x <= gen + 1); + bool foundSub1 = (mask_host[i].y >= 1 && mask_host[i].y <= gen + 1); + bool foundSub2 = (mask_host[i].z >= 1 && mask_host[i].z <= gen + 1); + + if (foundMain && foundSub1 && foundSub2) return; + + // search neighbor pixels' mask_host values + for (int yy = y - 1; yy <= y + 1; yy++) { + // boundary condition + if (yy < 0 || yy >= ly) continue; + + // current searching index + int curIndex = yy * lx + x - 1; + + for (int xx = x - 1; xx <= x + 1; xx++, curIndex++) { + // boundary condition + if (xx < 0 || xx >= lx) continue; + + // update the flags if the searching pixel is opac + if (!foundMain && mask_host[curIndex].x >= 1 && + mask_host[curIndex].x <= gen + 1) + foundMain = true; + if (!foundSub1 && mask_host[curIndex].y >= 1 && + mask_host[curIndex].y <= gen + 1) + foundSub1 = true; + if (!foundSub2 && mask_host[curIndex].z >= 1 && + mask_host[curIndex].z <= gen + 1) + foundSub2 = true; + + // end the loop when all colors are found + if (foundMain && foundSub1 && foundSub2) break; + } + // end the loop when all colors are found + if (foundMain && foundSub1 && foundSub2) break; + } + + // update mask_host + if (foundMain && mask_host[i].x == 0) mask_host[i].x = gen + 2; + if (foundSub1 && mask_host[i].y == 0) mask_host[i].y = gen + 2; + if (foundSub2 && mask_host[i].z == 0) mask_host[i].z = gen + 2; +} + +void expandMask(int x, int y, uchar4* mask_host, int lx, int ly, int gen) { + int i = y * lx + x; + // check if the target pixel is already opac + bool foundMain = (mask_host[i].x >= 1 && mask_host[i].x <= gen + 1); + bool foundSub1 = (mask_host[i].y >= 1 && mask_host[i].y <= gen + 1); + bool foundSub2 = (mask_host[i].z >= 1 && mask_host[i].z <= gen + 1); + bool foundSub3 = (mask_host[i].w >= 1 && mask_host[i].w <= gen + 1); + + if (foundMain && foundSub1 && foundSub2 && foundSub3) return; + + // search neighbor pixels' mask_host values + for (int yy = y - 1; yy <= y + 1; yy++) { + // boundary condition + if (yy < 0 || yy >= ly) continue; + + // current searching index + int curIndex = yy * lx + x - 1; + + for (int xx = x - 1; xx <= x + 1; xx++, curIndex++) { + // boundary condition + if (xx < 0 || xx >= lx) continue; + + // update the flags if the searching pixel is opac + if (!foundMain && mask_host[curIndex].x >= 1 && + mask_host[curIndex].x <= gen + 1) + foundMain = true; + if (!foundSub1 && mask_host[curIndex].y >= 1 && + mask_host[curIndex].y <= gen + 1) + foundSub1 = true; + if (!foundSub2 && mask_host[curIndex].z >= 1 && + mask_host[curIndex].z <= gen + 1) + foundSub2 = true; + if (!foundSub3 && mask_host[curIndex].w >= 1 && + mask_host[curIndex].w <= gen + 1) + foundSub3 = true; + + // end the loop when all colors are found + if (foundMain && foundSub1 && foundSub2 && foundSub3) break; + } + // end the loop when all colors are found + if (foundMain && foundSub1 && foundSub2 && foundSub3) break; + } + + // update mask_host + if (foundMain && mask_host[i].x == 0) mask_host[i].x = gen + 2; + if (foundSub1 && mask_host[i].y == 0) mask_host[i].y = gen + 2; + if (foundSub2 && mask_host[i].z == 0) mask_host[i].z = gen + 2; + if (foundSub3 && mask_host[i].w == 0) mask_host[i].w = gen + 2; +} + +TPixel32 BlueMaskColor(128, 128, 255); +TPixel32 RedMaskColor(255, 128, 128); +}; + +//------------------------------------------------------------------- + +void Separate3ColorsTask::run() { + for (int i = m_from; i < m_to; i++) { + separate3Colors(i, m_src, m_out, m_paper_xyz, m_main_xyz, m_sub1_xyz, + m_sub2_xyz, m_pane, m_mainAdjust, m_borderRatio); + } +} + +//------------------------------------------------------------------- + +void Separate4ColorsTask::run() { + for (int i = m_from; i < m_to; i++) { + separate4Colors(i, m_src, m_out, m_paper_xyz, m_main_xyz, m_sub1_xyz, + m_sub2_xyz, m_sub3_xyz, m_pane_m12, m_pane_m13, m_pane_m23, + m_pane_123, m_R, m_mainAdjust, m_borderRatio); + } +} + +//------------------------------------------------------------------- + +SeparateColorsPopup::SeparateColorsPopup() + : DVGui::Dialog(TApp::instance()->getMainWindow(), false, false, + "SeparateColors") + , m_isConverting(false) { + setModal(false); + setMinimumSize(900, 670); + + QSplitter* mainSplitter = new QSplitter(this); + + m_autoBtn = new QPushButton(tr("Auto"), this); + m_previewBtn = new QPushButton(tr("Preview"), this); + m_okBtn = new QPushButton(tr("Separate"), this); + m_cancelBtn = new QPushButton(tr("Close"), this); + m_fromFld = new IntLineEdit(this); + m_toFld = new IntLineEdit(this); + m_saveInFileFld = new FileField(0, QString("")); + m_fileFormatCombo = new QComboBox(this); + + m_paperColorField = + new DVGui::ColorField(this, false, TPixel32(249, 246, 243), 35, true, 55); + m_mainColorField = + new DVGui::ColorField(this, false, TPixel32(176, 171, 169), 35, true, 55); + m_subColor1Field = + new DVGui::ColorField(this, false, TPixel32(249, 164, 164), 35, true, 55); + m_subColor2Field = + new DVGui::ColorField(this, false, TPixel32(165, 227, 187), 35, true, 55); + + QLabel* color3Label = new QLabel(tr("Sub Color 3:"), this); + m_subColor3Field = + new DVGui::ColorField(this, false, TPixel32::Green, 35, true, 55); + + m_subColorAdjustFld = new DoubleField(this); + m_borderSmoothnessFld = new DoubleField(this); + + m_matteGroupBox = new QGroupBox(tr("Alpha Matting"), this); + m_matteThreshold = new DoubleField(this); + m_matteRadius = new IntField(this); + + m_notifier = new ImageUtils::FrameTaskNotifier(); + + m_outMainCB = new QCheckBox(tr("Main"), this); + m_outSub1CB = new QCheckBox(tr("Sub1"), this); + m_outSub2CB = new QCheckBox(tr("Sub2"), this); + m_outSub3CB = new QCheckBox(tr("Sub3"), this); + + m_mainSuffixEdit = new LineEdit(QString("_m")); + m_sub1SuffixEdit = new LineEdit(QString("_s1")); + m_sub2SuffixEdit = new LineEdit(QString("_s2")); + m_sub3SuffixEdit = new LineEdit(QString("_s3")); + + m_previewFrameField = new IntField(this); + m_previewFrameLabel = new QLabel(this); + + m_pickBtn = new QPushButton( + CommandManager::instance()->getAction("T_RGBPicker")->icon(), + tr("Pick Color"), this); + + QPixmap iconPm(13, 13); + iconPm.fill( + QColor((int)RedMaskColor.r, (int)RedMaskColor.g, (int)RedMaskColor.b)); + m_showMatteBtn = new QPushButton(QIcon(iconPm), tr("Show Mask"), this); + + { + iconPm.fill(Qt::black); + QPainter icon_p(&iconPm); + icon_p.setPen(Qt::NoPen); + icon_p.setBrush(Qt::white); + icon_p.drawEllipse(3, 3, 7, 7); + m_showAlphaBtn = new QPushButton(QIcon(iconPm), tr("Show Alpha"), this); + } + + m_separateSwatch = new SeparateSwatch(this, 200, 150); + + //---- + + m_autoBtn->setStyleSheet("font-size: 17px;"); + m_autoBtn->setFixedHeight(60); + m_autoBtn->setCheckable(true); + m_autoBtn->setChecked(true); + + m_previewBtn->setStyleSheet("font-size: 17px;"); + m_previewBtn->setFixedHeight(60); + m_previewBtn->setDisabled(true); + + m_okBtn->setStyleSheet("font-size: 17px;"); + m_okBtn->setFixedHeight(60); + + m_fileFormatCombo->addItem("png"); + m_fileFormatCombo->addItem("tif"); + + m_subColorAdjustFld->setRange(0.5, 10.0); + m_borderSmoothnessFld->setRange(0.0, 0.5); + m_subColorAdjustFld->setValue(3.0); + m_borderSmoothnessFld->setValue(0.1); + + m_matteGroupBox->setCheckable(true); + m_matteGroupBox->setChecked(true); + m_matteThreshold->setRange(0.0, 1.0); + m_matteRadius->setRange(0, 30); + m_matteThreshold->setValue(0.0); + m_matteRadius->setValue(0); + + m_outMainCB->setChecked(true); + m_outSub1CB->setChecked(true); + m_outSub2CB->setChecked(true); + + m_outSub3CB->setChecked(false); + m_sub3SuffixEdit->setEnabled(false); + color3Label->setVisible(false); + m_subColor3Field->setVisible(false); + + m_pickBtn->setMaximumWidth(130); + + m_showMatteBtn->setCheckable(true); + m_showMatteBtn->setChecked(true); + + m_showAlphaBtn->setCheckable(true); + m_showAlphaBtn->setChecked(false); + + //---- + { + QVBoxLayout* leftLay = new QVBoxLayout(); + leftLay->setMargin(5); + leftLay->setSpacing(5); + { + QHBoxLayout* previewLay = new QHBoxLayout(); + previewLay->setMargin(0); + previewLay->setSpacing(5); + { + previewLay->addWidget(new QLabel(tr("Preview Frame:"), this), 0, + Qt::AlignRight); + previewLay->addWidget(m_previewFrameField, 1); + previewLay->addWidget(m_previewFrameLabel, 0); + + previewLay->addSpacing(10); + + previewLay->addWidget(m_showMatteBtn, 0); + previewLay->addWidget(m_showAlphaBtn, 0); + + previewLay->addSpacing(20); + + previewLay->addWidget(m_pickBtn); + } + leftLay->addLayout(previewLay, 0); + + leftLay->addWidget(m_separateSwatch, 1); + } + QWidget* leftWidget = new QWidget(this); + leftWidget->setLayout(leftLay); + mainSplitter->addWidget(leftWidget); + + QVBoxLayout* rightLay = new QVBoxLayout(); + rightLay->setMargin(10); + rightLay->setSpacing(10); + { + QGridLayout* upperLay = new QGridLayout(); + upperLay->setMargin(0); + upperLay->setHorizontalSpacing(5); + upperLay->setVerticalSpacing(10); + { + upperLay->addWidget(new QLabel(tr("Paper Color:"), this), 0, 0, + Qt::AlignRight); + upperLay->addWidget(m_paperColorField, 0, 1); + upperLay->addWidget(new QLabel(tr("Main Color:"), this), 1, 0, + Qt::AlignRight); + upperLay->addWidget(m_mainColorField, 1, 1); + upperLay->addWidget(new QLabel(tr("Sub Color 1:"), this), 2, 0, + Qt::AlignRight); + upperLay->addWidget(m_subColor1Field, 2, 1); + upperLay->addWidget(new QLabel(tr("Sub Color 2:"), this), 3, 0, + Qt::AlignRight); + upperLay->addWidget(m_subColor2Field, 3, 1); + + upperLay->addWidget(color3Label, 4, 0, Qt::AlignRight); + upperLay->addWidget(m_subColor3Field, 4, 1); + + upperLay->addWidget(new QLabel(tr("Sub Adjust:"), this), 5, 0, + Qt::AlignRight); + upperLay->addWidget(m_subColorAdjustFld, 5, 1); + upperLay->addWidget(new QLabel(tr("Border Smooth:"), this), 6, 0, + Qt::AlignRight); + upperLay->addWidget(m_borderSmoothnessFld, 6, 1); + + QGridLayout* maskLay = new QGridLayout(); + maskLay->setMargin(10); + maskLay->setHorizontalSpacing(5); + maskLay->setVerticalSpacing(10); + { + maskLay->addWidget(new QLabel(tr("Mask Threshold:"), this), 0, 0, + Qt::AlignRight); + maskLay->addWidget(m_matteThreshold, 0, 1); + maskLay->addWidget(new QLabel(tr("Mask Radius:"), this), 1, 0, + Qt::AlignRight); + maskLay->addWidget(m_matteRadius, 1, 1); + } + maskLay->setColumnStretch(0, 0); + maskLay->setColumnStretch(1, 1); + m_matteGroupBox->setLayout(maskLay); + upperLay->addWidget(m_matteGroupBox, 7, 0, 1, 2); + } + upperLay->setColumnStretch(0, 0); + upperLay->setColumnStretch(1, 1); + + rightLay->addLayout(upperLay, 0); + + QGridLayout* middleLay = new QGridLayout(); + middleLay->setMargin(0); + middleLay->setHorizontalSpacing(5); + middleLay->setVerticalSpacing(10); + { + middleLay->addWidget(new QLabel(tr("Start:"), this), 0, 0, + Qt::AlignRight); + QHBoxLayout* rangeLay = new QHBoxLayout(); + rangeLay->setMargin(0); + rangeLay->setSpacing(5); + { + rangeLay->addWidget(m_fromFld, 0); + rangeLay->addSpacing(10); + rangeLay->addWidget(new QLabel(tr("End:"), this), 0); + rangeLay->addWidget(m_toFld, 0); + rangeLay->addStretch(1); + rangeLay->addWidget(new QLabel(tr("Format:"), this), 0); + rangeLay->addWidget(m_fileFormatCombo, 0); + } + middleLay->addLayout(rangeLay, 0, 1, 1, 6); + + middleLay->addWidget(new QLabel(tr("Save in:"), this), 1, 0, + Qt::AlignRight); + middleLay->addWidget(m_saveInFileFld, 1, 1, 1, 6); + + middleLay->addWidget(new QLabel(tr("File Suffix:"), this), 2, 0, + Qt::AlignRight); + middleLay->addWidget(m_outMainCB, 2, 1, + Qt::AlignRight | Qt::AlignVCenter); + middleLay->addWidget(m_mainSuffixEdit, 2, 2); + middleLay->addWidget(m_outSub1CB, 2, 4, + Qt::AlignRight | Qt::AlignVCenter); + middleLay->addWidget(m_sub1SuffixEdit, 2, 5); + + middleLay->addWidget(m_outSub2CB, 3, 1, + Qt::AlignRight | Qt::AlignVCenter); + middleLay->addWidget(m_sub2SuffixEdit, 3, 2); + middleLay->addWidget(m_outSub3CB, 3, 4, + Qt::AlignRight | Qt::AlignVCenter); + middleLay->addWidget(m_sub3SuffixEdit, 3, 5); + } + middleLay->setColumnStretch(0, 0); + middleLay->setColumnStretch(1, 0); + middleLay->setColumnStretch(2, 0); + middleLay->setColumnStretch(3, 0); + middleLay->setColumnStretch(4, 0); + middleLay->setColumnStretch(5, 0); + middleLay->setColumnStretch(6, 1); + rightLay->addLayout(middleLay, 0); + + rightLay->addSpacing(10); + + QHBoxLayout* buttonLay = new QHBoxLayout(); + buttonLay->setMargin(0); + buttonLay->setSpacing(0); + { + buttonLay->addWidget(m_autoBtn, 0); + buttonLay->addWidget(m_previewBtn, 1); + buttonLay->addSpacing(30); + buttonLay->addWidget(m_okBtn, 1); + } + rightLay->addLayout(buttonLay, 0); + rightLay->addSpacing(10); + rightLay->addWidget(m_cancelBtn, 0); + + rightLay->addStretch(1); + } + QWidget* widget = new QWidget(this); + widget->setLayout(rightLay); + + mainSplitter->addWidget(widget); + } + mainSplitter->setStretchFactor(0, 1); + mainSplitter->setStretchFactor(1, 0); + m_topLayout->addWidget(mainSplitter, 1); + + //---- + + bool ret = true; + + ret = ret && connect(m_autoBtn, SIGNAL(toggled(bool)), m_previewBtn, + SLOT(setDisabled(bool))); + ret = ret && connect(m_previewBtn, SIGNAL(clicked()), this, + SLOT(onPreviewBtnPressed())); + ret = ret && connect(m_okBtn, SIGNAL(clicked()), this, SLOT(separate())); + ret = ret && connect(m_cancelBtn, SIGNAL(clicked()), this, SLOT(reject())); + + m_progressDialog = new DVGui::ProgressDialog("", tr("Cancel"), 0, 0); + m_progressDialog->setWindowTitle(tr("Separate by colors ... ")); + m_progressDialog->setWindowFlags( + Qt::Dialog | Qt::WindowTitleHint); // Don't show ? and X buttons + // m_progressDialog->setWindowModality(Qt::WindowModal); + m_progressDialog->setMinimum(0); + m_progressDialog->setMaximum(100); + ret = ret && connect(m_notifier, SIGNAL(frameCompleted(int)), + m_progressDialog, SLOT(setValue(int))); + ret = ret && connect(m_progressDialog, SIGNAL(canceled()), m_notifier, + SLOT(onCancelTask())); + + ret = ret && connect(m_outMainCB, SIGNAL(toggled(bool)), m_mainSuffixEdit, + SLOT(setEnabled(bool))); + ret = ret && connect(m_outSub1CB, SIGNAL(toggled(bool)), m_sub1SuffixEdit, + SLOT(setEnabled(bool))); + ret = ret && connect(m_outSub2CB, SIGNAL(toggled(bool)), m_sub2SuffixEdit, + SLOT(setEnabled(bool))); + + ret = ret && connect(m_outSub3CB, SIGNAL(toggled(bool)), color3Label, + SLOT(setVisible(bool))); + ret = ret && connect(m_outSub3CB, SIGNAL(toggled(bool)), m_subColor3Field, + SLOT(setVisible(bool))); + ret = ret && connect(m_outSub3CB, SIGNAL(toggled(bool)), m_sub3SuffixEdit, + SLOT(setEnabled(bool))); + ret = ret && connect(m_outSub3CB, SIGNAL(toggled(bool)), m_separateSwatch, + SLOT(showSub3Swatch(bool))); + + ret = ret && connect(m_previewFrameField, SIGNAL(valueChanged(bool)), this, + SLOT(onPreviewFrameFieldValueChanged(bool))); + + QAction* pickScreenAction = + CommandManager::instance()->getAction("A_ToolOption_PickScreen"); + ret = ret && connect(m_pickBtn, SIGNAL(clicked()), pickScreenAction, + SLOT(trigger())); + + ret = ret && connect(m_matteGroupBox, SIGNAL(toggled(bool)), m_showMatteBtn, + SLOT(setEnabled(bool))); + + // auto preview update + ret = + ret && connect(m_autoBtn, SIGNAL(toggled(bool)), this, SLOT(onToggle())); + ret = ret && connect(m_subColorAdjustFld, SIGNAL(valueChanged(bool)), this, + SLOT(onChange(bool))); + ret = ret && connect(m_borderSmoothnessFld, SIGNAL(valueChanged(bool)), this, + SLOT(onChange(bool))); + ret = ret && + connect(m_matteGroupBox, SIGNAL(toggled(bool)), this, SLOT(onToggle())); + ret = ret && connect(m_matteThreshold, SIGNAL(valueChanged(bool)), this, + SLOT(onChange(bool))); + ret = ret && connect(m_matteRadius, SIGNAL(valueChanged(bool)), this, + SLOT(onChange(bool))); + ret = ret && + connect(m_outSub3CB, SIGNAL(toggled(bool)), this, SLOT(onToggle())); + ret = ret && + connect(m_paperColorField, SIGNAL(colorChanged(const TPixel32&, bool)), + this, SLOT(onColorChange(const TPixel32&, bool))); + ret = ret && + connect(m_mainColorField, SIGNAL(colorChanged(const TPixel32&, bool)), + this, SLOT(onColorChange(const TPixel32&, bool))); + ret = ret && + connect(m_subColor1Field, SIGNAL(colorChanged(const TPixel32&, bool)), + this, SLOT(onColorChange(const TPixel32&, bool))); + ret = ret && + connect(m_subColor2Field, SIGNAL(colorChanged(const TPixel32&, bool)), + this, SLOT(onColorChange(const TPixel32&, bool))); + ret = ret && + connect(m_subColor3Field, SIGNAL(colorChanged(const TPixel32&, bool)), + this, SLOT(onColorChange(const TPixel32&, bool))); + ret = ret && + connect(m_showMatteBtn, SIGNAL(toggled(bool)), this, SLOT(onToggle())); + ret = ret && + connect(m_showAlphaBtn, SIGNAL(toggled(bool)), this, SLOT(onToggle())); + + assert(ret); + + //----- reproduce UI + + QColor paperCol, mainCol, sub1Col, sub2Col, sub3Col; + paperCol.setNamedColor( + QString::fromStdString(SeparateColorsPopup_PaperColor.getValue())); + mainCol.setNamedColor( + QString::fromStdString(SeparateColorsPopup_MainColor.getValue())); + sub1Col.setNamedColor( + QString::fromStdString(SeparateColorsPopup_SubColor1.getValue())); + sub2Col.setNamedColor( + QString::fromStdString(SeparateColorsPopup_SubColor2.getValue())); + sub3Col.setNamedColor( + QString::fromStdString(SeparateColorsPopup_SubColor3.getValue())); + + m_paperColorField->setColor( + TPixel32(paperCol.red(), paperCol.green(), paperCol.blue())); + m_mainColorField->setColor( + TPixel32(mainCol.red(), mainCol.green(), mainCol.blue())); + m_subColor1Field->setColor( + TPixel32(sub1Col.red(), sub1Col.green(), sub1Col.blue())); + m_subColor2Field->setColor( + TPixel32(sub2Col.red(), sub2Col.green(), sub2Col.blue())); + m_subColor3Field->setColor( + TPixel32(sub3Col.red(), sub3Col.green(), sub3Col.blue())); + + m_subColorAdjustFld->setValue(SeparateColorsPopup_SubAdjust); + m_borderSmoothnessFld->setValue(SeparateColorsPopup_BorderSmooth); + + m_outMainCB->setChecked(SeparateColorsPopup_OutMain ? 1 : 0); + m_outSub1CB->setChecked(SeparateColorsPopup_OutSub1 ? 1 : 0); + m_outSub2CB->setChecked(SeparateColorsPopup_OutSub2 ? 1 : 0); + m_outSub3CB->setChecked(SeparateColorsPopup_OutSub3 ? 1 : 0); + + m_mainSuffixEdit->setText( + QString::fromStdString(SeparateColorsPopup_MainSuffix.getValue())); + m_sub1SuffixEdit->setText( + QString::fromStdString(SeparateColorsPopup_Sub1Suffix.getValue())); + m_sub2SuffixEdit->setText( + QString::fromStdString(SeparateColorsPopup_Sub2Suffix.getValue())); + m_sub3SuffixEdit->setText( + QString::fromStdString(SeparateColorsPopup_Sub3Suffix.getValue())); + + m_matteGroupBox->setChecked(SeparateColorsPopup_doMatte == 1 ? true : false); + m_matteThreshold->setValue(SeparateColorsPopup_MatteThreshold); + m_matteRadius->setValue(SeparateColorsPopup_MatteRadius); + + m_fileFormatCombo->setCurrentText( + QString::fromStdString(SeparateColorsPopup_FileFormat)); +} + +//------------------------------------------------------------------- + +void SeparateColorsPopup::onSeparateFinished() { + m_isConverting = false; + TFilePath dstFilePath(m_saveInFileFld->getPath().toStdWString()); + if (dstFilePath == m_srcFilePaths[0].getParentDir()) + FileBrowser::refreshFolder(dstFilePath); + + m_progressDialog->close(); +} + +//------------------------------------------------------------------- + +SeparateColorsPopup::~SeparateColorsPopup() { + delete m_notifier; + delete m_progressDialog; +} + +//------------------------------------------------------------------- + +bool SeparateColorsPopup::isConverting() { return m_isConverting; } + +//------------------------------------------------------------------- + +void SeparateColorsPopup::setFiles(const std::vector& fps) { + if (!m_srcFrames.isEmpty()) m_srcFrames.clear(); + + m_srcFilePaths = fps; + if (m_srcFilePaths.size() == 1) { + setWindowTitle(tr("Separate 1 Level")); + m_fromFld->setEnabled(true); + m_toFld->setEnabled(true); + + TLevelP levelTmp; + TLevelReaderP lrTmp = TLevelReaderP(fps[0]); + if (lrTmp) levelTmp = lrTmp->loadInfo(); + m_fromFld->setText("1"); + m_toFld->setText(QString::number(levelTmp->getFrameCount())); + + std::vector frames; + getFrameIds(1, levelTmp->getFrameCount(), levelTmp, frames); + for (int f = 0; f < frames.size(); f++) + m_srcFrames.append(qMakePair(fps[0], frames[f])); + } else { + setWindowTitle(tr("Separate %1 Levels").arg(m_srcFilePaths.size())); + m_fromFld->setText(""); + m_toFld->setText(""); + m_fromFld->setEnabled(false); + m_toFld->setEnabled(false); + for (int s = 0; s < fps.size(); s++) { + TLevelReaderP lrTmp = TLevelReaderP(fps[s]); + if (lrTmp) { + TLevelP levelTmp = lrTmp->loadInfo(); + std::vector frames; + getFrameIds(1, levelTmp->getFrameCount(), levelTmp, frames); + for (int f = 0; f < frames.size(); f++) + m_srcFrames.append(qMakePair(fps[s], frames[f])); + } + } + } + m_saveInFileFld->setPath(toQString(fps[0].getParentDir())); + + // update preview frames + m_previewFrameField->setRange(1, m_srcFrames.size()); + m_previewFrameField->setValue(1); + onPreviewFrameFieldValueChanged(true); +} + +//------------------------------------------------------------------- + +void SeparateColorsPopup::doSeparate(const TFilePath& source, int from, int to, + int framerate, + FrameTaskNotifier* frameNotifier, + bool do4Colors) { + QString msg; + + TLevelReaderP lr(source); + TLevelP level = lr->loadInfo(); + + TDimension res(0, 0); + std::string srcExt = source.getType(); + + std::vector frames; + getFrameIds(from, to, level, frames); + + TImageInfo* ii = (TImageInfo*)lr->getImageInfo(frames[0]); + TPropertyGroup* prop = ii->m_properties; + + // destination folder + TFilePath dstFolder(m_saveInFileFld->getPath().toStdWString()); + dstFolder = TApp::instance()->getCurrentScene()->getScene()->decodeFilePath( + dstFolder); + + // file type + std::string ext = m_fileFormatCombo->currentText().toStdString(); + + TFilePath dest_m = + source.withParentDir(dstFolder) + .withName(source.getName() + m_mainSuffixEdit->text().toStdString()) + .withType(ext); + TFilePath dest_c1 = + source.withParentDir(dstFolder) + .withName(source.getName() + m_sub1SuffixEdit->text().toStdString()) + .withType(ext); + TFilePath dest_c2 = + source.withParentDir(dstFolder) + .withName(source.getName() + m_sub2SuffixEdit->text().toStdString()) + .withType(ext); + TFilePath dest_c3 = + source.withParentDir(dstFolder) + .withName(source.getName() + m_sub3SuffixEdit->text().toStdString()) + .withType(ext); + + if (!TSystem::touchParentDir(dest_m)) { + QMessageBox::critical(this, tr("Critical"), + tr("Failed to access the destination folder!")); + return; + } + + TPropertyGroup* propForWrite = (m_matteGroupBox->isChecked()) ? 0 : prop; + + TLevelWriterP lw_m(dest_m, propForWrite); + TLevelWriterP lw_c1(dest_c1, propForWrite); + TLevelWriterP lw_c2(dest_c2, propForWrite); + TLevelWriterP lw_c3(dest_c3, propForWrite); + + lw_m->setFrameRate(framerate); + lw_c1->setFrameRate(framerate); + lw_c2->setFrameRate(framerate); + lw_c3->setFrameRate(framerate); + + bool outMain = m_outMainCB->isChecked(); + bool outSub1 = m_outSub1CB->isChecked(); + bool outSub2 = m_outSub2CB->isChecked(); + bool outSub3 = do4Colors; + + // for each frame + for (int i = 0; i < (int)frames.size(); i++) { + if (frameNotifier->abortTask()) break; + + TImageReaderP ir = lr->getFrameReader(frames[i]); + TRasterImageP img = ir->load(); + double xDpi, yDpi; + img->getDpi(xDpi, yDpi); + + TDimensionI dim = convert(img->getBBox()).getSize(); + + TRaster32P raster(dim); + raster = img->getRaster(); + raster->lock(); + + TRaster32P ras_m(dim); + ras_m->lock(); + TRaster32P ras_c1(dim); + ras_c1->lock(); + TRaster32P ras_c2(dim); + ras_c2->lock(); + + if (!do4Colors) { + doCompute(raster, dim, ras_m, ras_c1, ras_c2); + } else { + TRaster32P ras_c3(dim); + ras_c3->lock(); + doCompute(raster, dim, ras_m, ras_c1, ras_c2, ras_c3); + TRasterImageP newImg_c3(ras_c3); + newImg_c3->setDpi(xDpi, yDpi); + TImageWriterP iw_c3 = lw_c3->getFrameWriter(frames[i]); + iw_c3->save(newImg_c3); + ras_c3->unlock(); + } + + TRasterImageP newImg_m(ras_m); + TRasterImageP newImg_c1(ras_c1); + TRasterImageP newImg_c2(ras_c2); + + newImg_m->setDpi(xDpi, yDpi); + newImg_c1->setDpi(xDpi, yDpi); + newImg_c2->setDpi(xDpi, yDpi); + + if (outMain) { + TImageWriterP iw_m = lw_m->getFrameWriter(frames[i]); + iw_m->save(newImg_m); + } + if (outSub1) { + TImageWriterP iw_c1 = lw_c1->getFrameWriter(frames[i]); + iw_c1->save(newImg_c1); + } + if (outSub2) { + TImageWriterP iw_c2 = lw_c2->getFrameWriter(frames[i]); + iw_c2->save(newImg_c2); + } + + raster->unlock(); + ras_m->unlock(); + ras_c1->unlock(); + ras_c2->unlock(); + + // this notification is for updating the progress bar. + // thus, not frameId but the amount of finished frames is thrown. + frameNotifier->notifyFrameCompleted(100 * (i + 1) / frames.size()); + } +} + +//------------------------------------------------------------------- + +void SeparateColorsPopup::doPreview(TRaster32P& orgRas, TRaster32P& mainRas, + TRaster32P& sub1Ras, TRaster32P& sub2Ras, + TRaster32P& sub3Ras) { + if (m_srcFrames.isEmpty()) return; + + TPixel paperColor = m_paperColorField->getColor(); + TPixel mainColor = m_mainColorField->getColor(); + TPixel subColor1 = m_subColor1Field->getColor(); + TPixel subColor2 = m_subColor2Field->getColor(); + TPixel subColor3 = m_subColor3Field->getColor(); + + bool do4Colors = m_outSub3CB->isChecked(); + + // specify the transparent colors + bool showAlpha = m_showAlphaBtn->isChecked(); + m_separateSwatch->setTranspColors(mainColor, subColor1, subColor2, subColor3, + showAlpha); + + int frame = m_previewFrameField->getValue() - 1; + TFilePath fp = m_srcFrames[frame].first; + TFrameId fId = m_srcFrames[frame].second; + + TLevelReaderP lr(fp); + TImageReaderP ir = lr->getFrameReader(fId); + + TRasterImageP img = ir->load(); + TDimensionI dim = convert(img->getBBox()).getSize(); + + orgRas = img->getRaster(); + mainRas = TRaster32P(dim); + sub1Ras = TRaster32P(dim); + sub2Ras = TRaster32P(dim); + + if (!do4Colors) { + doCompute(orgRas, dim, mainRas, sub1Ras, sub2Ras, true); + } else { + sub3Ras = TRaster32P(dim); + doCompute(orgRas, dim, mainRas, sub1Ras, sub2Ras, sub3Ras, true); + } +} + +//------------------------------------------------------------------- + +void SeparateColorsPopup::doCompute(TRaster32P raster, TDimensionI& dim, + TRaster32P ras_m, TRaster32P ras_c1, + TRaster32P ras_c2, bool isPreview) { + TPixel paperColor = m_paperColorField->getColor(); + TPixel mainColor = m_mainColorField->getColor(); + TPixel subColor1 = m_subColor1Field->getColor(); + TPixel subColor2 = m_subColor2Field->getColor(); + + // alpha matting + float matteThres = (float)(m_matteThreshold->getValue()); + int matteRadius = m_matteRadius->getValue(); + bool doMatte = m_matteGroupBox->isChecked() && matteThres > 0.0f; + + // intensity of each color is to be stored + QVector3D* out_host; + TRasterGR8P out_host_ras(sizeof(QVector3D) * dim.lx * dim.ly, 1); + out_host_ras->lock(); + out_host = (QVector3D*)out_host_ras->getRawData(); + + QVector3D* src_host; + TRasterGR8P src_host_ras(sizeof(QVector3D) * dim.lx * dim.ly, 1); + src_host_ras->lock(); + src_host = (QVector3D*)src_host_ras->getRawData(); + + // matte information + uchar3* matte_host = nullptr; + TRasterGR8P matte_host_ras; + if (doMatte) { + matte_host_ras = TRasterGR8P(sizeof(uchar3) * dim.lx * dim.ly, 1); + matte_host_ras->lock(); + matte_host = (uchar3*)matte_host_ras->getRawData(); + } + + // input the souce image + QVector3D* chann_p = src_host; + for (int j = 0; j < dim.ly; j++) { + TPixel32* pix = raster->pixels(j); + for (int i = 0; i < dim.lx; i++, chann_p++, pix++) { + (*chann_p).setX((float)pix->r / (float)TPixel32::maxChannelValue); + (*chann_p).setY((float)pix->g / (float)TPixel32::maxChannelValue); + (*chann_p).setZ((float)pix->b / (float)TPixel32::maxChannelValue); + } + } + + QVector3D paper_xyz = myHls2Xyz(myRgb2Hls(myPix2Rgb(paperColor))); + QVector3D main_xyz = myHls2Xyz(myRgb2Hls(myPix2Rgb(mainColor))); + QVector3D sub1_xyz = myHls2Xyz(myRgb2Hls(myPix2Rgb(subColor1))); + QVector3D sub2_xyz = myHls2Xyz(myRgb2Hls(myPix2Rgb(subColor2))); + + // obtain the factors of plane equation : ax + by + cz = d + QVector4D pane = getPane(main_xyz, sub1_xyz, sub2_xyz); + + int maxThreadCount = + std::max(1, QThreadPool::globalInstance()->maxThreadCount() / 2); + int start = 0; + for (int t = 0; t < maxThreadCount; t++) { + int end = (int)std::round((float)(dim.lx * dim.ly * (t + 1)) / + (float)maxThreadCount); + + Separate3ColorsTask* task = new Separate3ColorsTask( + start, end, src_host, out_host, paper_xyz, main_xyz, sub1_xyz, sub2_xyz, + pane, (float)m_subColorAdjustFld->getValue(), + (float)m_borderSmoothnessFld->getValue()); + + QThreadPool::globalInstance()->start(task); + + start = end; + } + + QThreadPool::globalInstance()->waitForDone(); + + src_host_ras->unlock(); + + if (doMatte) { + // mask by threshold, then expand it + for (int i = 0; i < dim.lx * dim.ly; i++) { + maskByThres(i, out_host, matte_host, matteThres); + } + + for (int r = 0; r < matteRadius; r++) { + for (int y = 0; y < dim.ly; y++) { + for (int x = 0; x < dim.lx; x++) { + expandMask(x, y, matte_host, dim.lx, dim.ly, r); + } + } + } + } + + auto getChannelValue = [](unsigned char pencil_chanVal, + float ratio) -> unsigned char { + return (unsigned char)(std::round((float)pencil_chanVal * ratio)); + }; + + bool showMask = m_showMatteBtn->isChecked(); + auto getMatteColor = [&](TPixel32 lineColor) -> TPixel32 { + if (!isPreview || !showMask) return TPixel32::Transparent; + TPixelD lineColorD = toPixelD(lineColor); + double h, l, s; + rgb2hls(lineColorD.r, lineColorD.g, lineColorD.b, &h, &l, &s); + // if the specified color is reddish, use blue color for transparent area + if ((h <= 30.0 || 330.0 <= h) && s >= 0.2) + return BlueMaskColor; + else + return RedMaskColor; + }; + + TPixel32 matteColor_m = getMatteColor(mainColor); + TPixel32 matteColor_s1 = getMatteColor(subColor1); + TPixel32 matteColor_s2 = getMatteColor(subColor2); + + // show alpha channel + if (isPreview && m_showAlphaBtn->isChecked()) { + mainColor = TPixel::White; + subColor1 = TPixel::White; + subColor2 = TPixel::White; + } + + // compute result + QVector3D* ratio_p = out_host; + uchar3* matte_p = matte_host; + for (int j = 0; j < dim.ly; j++) { + TPixel32* pix_m = ras_m->pixels(j); + TPixel32* pix_c1 = ras_c1->pixels(j); + TPixel32* pix_c2 = ras_c2->pixels(j); + for (int i = 0; i < dim.lx; i++, ratio_p++, pix_m++, pix_c1++, pix_c2++) { + // main + if (!doMatte || (*matte_p).x > 0) { + float ratio_m = (*ratio_p).x(); + if (doMatte) + ratio_m *= + (float)(matteRadius + 1 - (int)(*matte_p).x) / (float)matteRadius; + ratio_m = std::min(1.0f, ratio_m); + + pix_m->r = getChannelValue(mainColor.r, ratio_m); + pix_m->g = getChannelValue(mainColor.g, ratio_m); + pix_m->b = getChannelValue(mainColor.b, ratio_m); + pix_m->m = getChannelValue(TPixel32::maxChannelValue, ratio_m); + } else { + *pix_m = matteColor_m; + } + + // sub1 + if (!doMatte || (*matte_p).y > 0) { + float ratio_s1 = (*ratio_p).y(); + if (doMatte) + ratio_s1 *= + (float)(matteRadius + 1 - (int)(*matte_p).y) / (float)matteRadius; + ratio_s1 = std::min(1.0f, ratio_s1); + + pix_c1->r = getChannelValue(subColor1.r, ratio_s1); + pix_c1->g = getChannelValue(subColor1.g, ratio_s1); + pix_c1->b = getChannelValue(subColor1.b, ratio_s1); + pix_c1->m = getChannelValue(TPixel32::maxChannelValue, ratio_s1); + } else { + *pix_c1 = matteColor_s1; + } + + // sub2 + if (!doMatte || (*matte_p).z > 0) { + float ratio_s2 = (*ratio_p).z(); + if (doMatte) + ratio_s2 *= + (float)(matteRadius + 1 - (int)(*matte_p).z) / (float)matteRadius; + ratio_s2 = std::min(1.0f, ratio_s2); + + pix_c2->r = getChannelValue(subColor2.r, ratio_s2); + pix_c2->g = getChannelValue(subColor2.g, ratio_s2); + pix_c2->b = getChannelValue(subColor2.b, ratio_s2); + pix_c2->m = getChannelValue(TPixel32::maxChannelValue, ratio_s2); + } else { + *pix_c2 = matteColor_s2; + } + + if (doMatte) matte_p++; + } + } + out_host_ras->unlock(); + + if (doMatte) matte_host_ras->unlock(); +} + +//------------------------------------------------------------------- +// 4colors version + +void SeparateColorsPopup::doCompute(TRaster32P raster, TDimensionI& dim, + TRaster32P ras_m, TRaster32P ras_c1, + TRaster32P ras_c2, TRaster32P ras_c3, + bool isPreview) { + TPixel paperColor = m_paperColorField->getColor(); + TPixel mainColor = m_mainColorField->getColor(); + TPixel subColor1 = m_subColor1Field->getColor(); + TPixel subColor2 = m_subColor2Field->getColor(); + TPixel subColor3 = m_subColor3Field->getColor(); + + // alpha matting + float matteThres = (float)(m_matteThreshold->getValue()); + int matteRadius = m_matteRadius->getValue(); + bool doMatte = m_matteGroupBox->isChecked() && matteThres > 0.0f; + + // intensity of each color is to be stored + QVector4D* out_host; + TRasterGR8P out_host_ras(sizeof(QVector4D) * dim.lx * dim.ly, 1); + out_host_ras->lock(); + out_host = (QVector4D*)out_host_ras->getRawData(); + + QVector3D* src_host; + TRasterGR8P src_host_ras(sizeof(QVector3D) * dim.lx * dim.ly, 1); + src_host_ras->lock(); + src_host = (QVector3D*)src_host_ras->getRawData(); + + // matte information + uchar4* matte_host = nullptr; + TRasterGR8P matte_host_ras; + if (doMatte) { + matte_host_ras = TRasterGR8P(sizeof(uchar4) * dim.lx * dim.ly, 1); + matte_host_ras->lock(); + matte_host = (uchar4*)matte_host_ras->getRawData(); + } + + // input the souce image + QVector3D* chann_p = src_host; + for (int j = 0; j < dim.ly; j++) { + TPixel32* pix = raster->pixels(j); + for (int i = 0; i < dim.lx; i++, chann_p++, pix++) { + (*chann_p).setX((float)pix->r / (float)TPixel32::maxChannelValue); + (*chann_p).setY((float)pix->g / (float)TPixel32::maxChannelValue); + (*chann_p).setZ((float)pix->b / (float)TPixel32::maxChannelValue); + } + } + + QVector3D paper_xyz = myHls2Xyz(myRgb2Hls(myPix2Rgb(paperColor))); + QVector3D main_xyz = myHls2Xyz(myRgb2Hls(myPix2Rgb(mainColor))); + QVector3D sub1_xyz = myHls2Xyz(myRgb2Hls(myPix2Rgb(subColor1))); + QVector3D sub2_xyz = myHls2Xyz(myRgb2Hls(myPix2Rgb(subColor2))); + QVector3D sub3_xyz = myHls2Xyz(myRgb2Hls(myPix2Rgb(subColor3))); + + // obtain the plane equations intersecting three colors + // plane of main, sub1, and sub2 + QVector4D pane_m12 = getPane(main_xyz, sub1_xyz, sub2_xyz); + // plane of main, sub1, and sub3 + QVector4D pane_m13 = getPane(main_xyz, sub1_xyz, sub3_xyz); + // plane of main, sub2, and sub3 + QVector4D pane_m23 = getPane(main_xyz, sub2_xyz, sub3_xyz); + // plane of sub1, sub2, and sub3 + QVector4D pane_123 = getPane(sub1_xyz, sub2_xyz, sub3_xyz); + + // vector paper -> main color + QVector3D vec_pm = main_xyz - paper_xyz; + + float de = pane_123.x() * vec_pm.x() + pane_123.y() * vec_pm.y() + + pane_123.z() * vec_pm.z(); + float t = (pane_123.w() - + (pane_123.x() * paper_xyz.x() + pane_123.y() * paper_xyz.y() + + pane_123.z() * paper_xyz.z())) / + de; + + // intersection of paper-main vector and the plane 123 + QVector3D R = paper_xyz + t * vec_pm; + + int maxThreadCount = + std::max(1, QThreadPool::globalInstance()->maxThreadCount() / 2); + int start = 0; + for (int t = 0; t < maxThreadCount; t++) { + int end = (int)std::round((float)(dim.lx * dim.ly * (t + 1)) / + (float)maxThreadCount); + + Separate4ColorsTask* task = new Separate4ColorsTask( + start, end, src_host, out_host, paper_xyz, main_xyz, sub1_xyz, sub2_xyz, + sub3_xyz, pane_m12, pane_m13, pane_m23, pane_123, R, + (float)m_subColorAdjustFld->getValue(), + (float)m_borderSmoothnessFld->getValue()); + + QThreadPool::globalInstance()->start(task); + + start = end; + } + + QThreadPool::globalInstance()->waitForDone(); + + src_host_ras->unlock(); + + if (doMatte) { + // mask by threshold, then expand it + for (int i = 0; i < dim.lx * dim.ly; i++) { + maskByThres(i, out_host, matte_host, matteThres); + } + + for (int r = 0; r < matteRadius; r++) { + for (int y = 0; y < dim.ly; y++) { + for (int x = 0; x < dim.lx; x++) { + expandMask(x, y, matte_host, dim.lx, dim.ly, r); + } + } + } + } + + auto getChannelValue = [](unsigned char pencil_chanVal, + float ratio) -> unsigned char { + return (unsigned char)(std::round((float)pencil_chanVal * ratio)); + }; + + bool showMask = m_showMatteBtn->isChecked(); + auto getMatteColor = [&](TPixel32 lineColor) -> TPixel32 { + if (!isPreview || !showMask) return TPixel32::Transparent; + TPixelD lineColorD = toPixelD(lineColor); + double h, l, s; + rgb2hls(lineColorD.r, lineColorD.g, lineColorD.b, &h, &l, &s); + // if the specified color is reddish, use blue color for transparent area + if ((h <= 30.0 || 330.0 <= h) && s >= 0.2) + return BlueMaskColor; + else + return RedMaskColor; + }; + + TPixel32 matteColor_m = getMatteColor(mainColor); + TPixel32 matteColor_s1 = getMatteColor(subColor1); + TPixel32 matteColor_s2 = getMatteColor(subColor2); + TPixel32 matteColor_s3 = getMatteColor(subColor3); + + // show alpha channel + if (isPreview && m_showAlphaBtn->isChecked()) { + mainColor = TPixel::White; + subColor1 = TPixel::White; + subColor2 = TPixel::White; + subColor3 = TPixel::White; + } + + // compute result + QVector4D* ratio_p = out_host; + uchar4* matte_p = matte_host; + for (int j = 0; j < dim.ly; j++) { + TPixel32* pix_m = ras_m->pixels(j); + TPixel32* pix_c1 = ras_c1->pixels(j); + TPixel32* pix_c2 = ras_c2->pixels(j); + TPixel32* pix_c3 = ras_c3->pixels(j); + for (int i = 0; i < dim.lx; + i++, ratio_p++, pix_m++, pix_c1++, pix_c2++, pix_c3++) { + // main + if (!doMatte || (*matte_p).x > 0) { + float ratio_m = (*ratio_p).x(); + if (doMatte) + ratio_m *= + (float)(matteRadius + 1 - (int)(*matte_p).x) / (float)matteRadius; + ratio_m = std::min(1.0f, ratio_m); + + pix_m->r = getChannelValue(mainColor.r, ratio_m); + pix_m->g = getChannelValue(mainColor.g, ratio_m); + pix_m->b = getChannelValue(mainColor.b, ratio_m); + pix_m->m = getChannelValue(TPixel32::maxChannelValue, ratio_m); + } else { + *pix_m = matteColor_m; + } + + // sub1 + if (!doMatte || (*matte_p).y > 0) { + float ratio_s1 = (*ratio_p).y(); + if (doMatte) + ratio_s1 *= + (float)(matteRadius + 1 - (int)(*matte_p).y) / (float)matteRadius; + ratio_s1 = std::min(1.0f, ratio_s1); + + pix_c1->r = getChannelValue(subColor1.r, ratio_s1); + pix_c1->g = getChannelValue(subColor1.g, ratio_s1); + pix_c1->b = getChannelValue(subColor1.b, ratio_s1); + pix_c1->m = getChannelValue(TPixel32::maxChannelValue, ratio_s1); + } else { + *pix_c1 = matteColor_s1; + } + + // sub2 + if (!doMatte || (*matte_p).z > 0) { + float ratio_s2 = (*ratio_p).z(); + if (doMatte) + ratio_s2 *= + (float)(matteRadius + 1 - (int)(*matte_p).z) / (float)matteRadius; + ratio_s2 = std::min(1.0f, ratio_s2); + + pix_c2->r = getChannelValue(subColor2.r, ratio_s2); + pix_c2->g = getChannelValue(subColor2.g, ratio_s2); + pix_c2->b = getChannelValue(subColor2.b, ratio_s2); + pix_c2->m = getChannelValue(TPixel32::maxChannelValue, ratio_s2); + } else { + *pix_c2 = matteColor_s2; + } + + // sub3 + if (!doMatte || (*matte_p).w > 0) { + float ratio_s3 = (*ratio_p).w(); + if (doMatte) + ratio_s3 *= + (float)(matteRadius + 1 - (int)(*matte_p).w) / (float)matteRadius; + ratio_s3 = std::min(1.0f, ratio_s3); + + pix_c3->r = getChannelValue(subColor3.r, ratio_s3); + pix_c3->g = getChannelValue(subColor3.g, ratio_s3); + pix_c3->b = getChannelValue(subColor3.b, ratio_s3); + pix_c3->m = getChannelValue(TPixel32::maxChannelValue, ratio_s3); + } else { + *pix_c3 = matteColor_s3; + } + + if (doMatte) matte_p++; + } + } + out_host_ras->unlock(); + + if (doMatte) matte_host_ras->unlock(); +} + +void SeparateColorsPopup::showEvent(QShowEvent* e) { onPreviewBtnPressed(); } + +//------------------------------------------------------------------- +// store the current value to user env file + +void SeparateColorsPopup::hideEvent(QHideEvent* e) { + TPixel32 col = m_paperColorField->getColor(); + SeparateColorsPopup_PaperColor = + QColor(col.r, col.g, col.b).name().toStdString(); + col = m_mainColorField->getColor(); + SeparateColorsPopup_MainColor = + QColor(col.r, col.g, col.b).name().toStdString(); + col = m_subColor1Field->getColor(); + SeparateColorsPopup_SubColor1 = + QColor(col.r, col.g, col.b).name().toStdString(); + col = m_subColor2Field->getColor(); + SeparateColorsPopup_SubColor2 = + QColor(col.r, col.g, col.b).name().toStdString(); + col = m_subColor3Field->getColor(); + SeparateColorsPopup_SubColor3 = + QColor(col.r, col.g, col.b).name().toStdString(); + + SeparateColorsPopup_SubAdjust = m_subColorAdjustFld->getValue(); + SeparateColorsPopup_BorderSmooth = m_borderSmoothnessFld->getValue(); + SeparateColorsPopup_OutMain = (int)m_outMainCB->isChecked(); + SeparateColorsPopup_OutSub1 = (int)m_outSub1CB->isChecked(); + SeparateColorsPopup_OutSub2 = (int)m_outSub2CB->isChecked(); + SeparateColorsPopup_OutSub3 = (int)m_outSub3CB->isChecked(); + + SeparateColorsPopup_MainSuffix = m_mainSuffixEdit->text().toStdString(); + SeparateColorsPopup_Sub1Suffix = m_sub1SuffixEdit->text().toStdString(); + SeparateColorsPopup_Sub2Suffix = m_sub2SuffixEdit->text().toStdString(); + SeparateColorsPopup_Sub3Suffix = m_sub3SuffixEdit->text().toStdString(); + + SeparateColorsPopup_doMatte = (int)m_matteGroupBox->isChecked(); + SeparateColorsPopup_MatteThreshold = m_matteThreshold->getValue(); + SeparateColorsPopup_MatteRadius = m_matteRadius->getValue(); + + SeparateColorsPopup_FileFormat = + m_fileFormatCombo->currentText().toStdString(); +} + +//------------------------------------------------------------------- + +void SeparateColorsPopup::separate() { + if (!m_outMainCB->isChecked() && !m_outSub1CB->isChecked() && + !m_outSub2CB->isChecked() && !m_outSub3CB->isChecked()) + return; + + m_isConverting = true; + m_progressDialog->show(); + + m_notifier->reset(); + int from = -1; + int to = -1; + + for (int i = 0; !m_notifier->abortTask() && i < m_srcFilePaths.size(); i++) { + QString label; + TFilePath dstFilePath; + if (m_srcFilePaths.size() == 1) { + from = m_fromFld->text().toInt(); + to = m_toFld->text().toInt(); + label = QString( + tr("Separating %1") + .arg(QString::fromStdString(m_srcFilePaths[i].getLevelName()))); + } else { + TLevelP levelTmp; + TLevelReaderP lrTmp = TLevelReaderP(m_srcFilePaths[i]); + if (lrTmp) levelTmp = lrTmp->loadInfo(); + from = 1; + to = levelTmp->getFrameCount(); + label = QString( + tr("Converting level %1 of %2: %3") + .arg(i + 1) + .arg(m_srcFilePaths.size()) + .arg(QString::fromStdString(m_srcFilePaths[i].getLevelName()))); + } + + m_progressDialog->setLabelText(label); + + m_notifier->notifyFrameCompleted(0); + + TOutputProperties* oprop = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProperties() + ->getOutputProperties(); + int framerate = oprop->getFrameRate(); + + doSeparate(m_srcFilePaths[i], from, to, framerate, m_notifier, + m_outSub3CB->isChecked()); + } + + onSeparateFinished(); +} + +//------------------------------------------------------------------- + +void SeparateColorsPopup::onPreviewBtnPressed() { + TRaster32P orgRas, mainRas, sub1Ras, sub2Ras, sub3Ras; + doPreview(orgRas, mainRas, sub1Ras, sub2Ras, sub3Ras); + if (m_outSub3CB->isChecked()) + m_separateSwatch->setRaster(orgRas, mainRas, sub1Ras, sub2Ras, sub3Ras); + else + m_separateSwatch->setRaster(orgRas, mainRas, sub1Ras, sub2Ras); +} + +//------------------------------------------------------------------- + +void SeparateColorsPopup::onPreviewFrameFieldValueChanged(bool isDragging) { + int frame = m_previewFrameField->getValue(); + if (frame > m_srcFrames.size()) return; + + TFilePath fp = m_srcFrames.at(frame - 1).first; + TFrameId fId = m_srcFrames.at(frame - 1).second; + + m_previewFrameLabel->setText(QString::fromStdWString( + fp.withFrame(fId).withoutParentDir().getWideString())); + + onChange(isDragging); +} + +//------------------------------------------------------------------- + +void SeparateColorsPopup::onChange(bool isDragging) { + // if autopreview is activated + if (m_autoBtn->isChecked() && !isDragging && !m_srcFrames.isEmpty()) + onPreviewBtnPressed(); +} + +//============================================================================= +// SeparateColorsPopupCommand +//----------------------------------------------------------------------------- + +OpenPopupCommandHandler openSeparateColorsPopup( + MI_SeparateColors); diff --git a/toonz/sources/toonz/separatecolorspopup.h b/toonz/sources/toonz/separatecolorspopup.h new file mode 100644 index 0000000..6b04674 --- /dev/null +++ b/toonz/sources/toonz/separatecolorspopup.h @@ -0,0 +1,185 @@ +#pragma once +//============================================================================= +// SeparateColorsPopup +//----------------------------------------------------------------------------- +#ifndef SEPARATECOLORSPOPUP_H +#define SEPARATECOLORSPOPUP_H + +#include "tfilepath.h" +#include "tpixel.h" +#include "traster.h" +#include "toonzqt/dvdialog.h" + +#include +#include +#include +#include +#include + +class QLabel; +class QCheckBox; +class QGroupBox; +class QComboBox; + +class SeparateSwatch; +namespace DVGui { +class IntLineEdit; +class FileField; +class LineEdit; +class ColorField; +class ProgressDialog; +class CheckBox; +class DoubleField; +class IntField; +} + +namespace ImageUtils { +class FrameTaskNotifier; +} + +using namespace DVGui; +using namespace ImageUtils; + +//---------------------------------- + +class Separate4ColorsTask : public QRunnable { + int m_from, m_to; + QVector3D* m_src; + QVector4D* m_out; + const QVector3D m_paper_xyz, m_main_xyz, m_sub1_xyz, m_sub2_xyz, m_sub3_xyz; + const QVector4D m_pane_m12, m_pane_m13, m_pane_m23, m_pane_123; + const QVector3D m_R; + const float m_mainAdjust; + const float m_borderRatio; + + void run(); + +public: + Separate4ColorsTask(int from, int to, QVector3D* src, QVector4D* out, + const QVector3D paper_xyz, const QVector3D main_xyz, + const QVector3D sub1_xyz, const QVector3D sub2_xyz, + const QVector3D sub3_xyz, const QVector4D pane_m12, + const QVector4D pane_m13, const QVector4D pane_m23, + const QVector4D pane_123, const QVector3D R, + const float mainAdjust, const float borderRatio) + : m_from(from) + , m_to(to) + , m_src(src) + , m_out(out) + , m_paper_xyz(paper_xyz) + , m_main_xyz(main_xyz) + , m_sub1_xyz(sub1_xyz) + , m_sub2_xyz(sub2_xyz) + , m_sub3_xyz(sub3_xyz) + , m_pane_m12(pane_m12) + , m_pane_m13(pane_m13) + , m_pane_m23(pane_m23) + , m_pane_123(pane_123) + , m_R(R) + , m_mainAdjust(mainAdjust) + , m_borderRatio(borderRatio) {} +}; + +//---------------------------------- + +class Separate3ColorsTask : public QRunnable { + int m_from, m_to; + QVector3D *m_src, *m_out; + const QVector3D m_paper_xyz, m_main_xyz, m_sub1_xyz, m_sub2_xyz; + const QVector4D m_pane; + const float m_mainAdjust; + const float m_borderRatio; + + void run(); + +public: + Separate3ColorsTask(int from, int to, QVector3D* src, QVector3D* out, + const QVector3D paper_xyz, const QVector3D main_xyz, + const QVector3D sub1_xyz, const QVector3D sub2_xyz, + const QVector4D pane, const float mainAdjust, + const float borderRatio) + : m_from(from) + , m_to(to) + , m_src(src) + , m_out(out) + , m_paper_xyz(paper_xyz) + , m_main_xyz(main_xyz) + , m_sub1_xyz(sub1_xyz) + , m_sub2_xyz(sub2_xyz) + , m_pane(pane) + , m_mainAdjust(mainAdjust) + , m_borderRatio(borderRatio) {} +}; + +//---------------------------------- + +class SeparateColorsPopup : public DVGui::Dialog { + Q_OBJECT + + FrameTaskNotifier* m_notifier; + QPushButton *m_previewBtn, *m_okBtn, *m_cancelBtn, *m_autoBtn; + IntLineEdit *m_fromFld, *m_toFld; + FileField* m_saveInFileFld; + QComboBox* m_fileFormatCombo; + + DoubleField *m_subColorAdjustFld, *m_borderSmoothnessFld; + + QGroupBox* m_matteGroupBox; + DoubleField* m_matteThreshold; + IntField* m_matteRadius; + + ColorField *m_paperColorField, *m_mainColorField, *m_subColor1Field, + *m_subColor2Field, *m_subColor3Field; + + QCheckBox *m_outMainCB, *m_outSub1CB, *m_outSub2CB, *m_outSub3CB; + LineEdit *m_mainSuffixEdit, *m_sub1SuffixEdit, *m_sub2SuffixEdit, + *m_sub3SuffixEdit; + + IntField* m_previewFrameField; + QLabel* m_previewFrameLabel; + QVector> m_srcFrames; + + QPushButton *m_pickBtn, *m_showMatteBtn, *m_showAlphaBtn; + SeparateSwatch* m_separateSwatch; + + ProgressDialog* m_progressDialog; + std::vector m_srcFilePaths; + bool m_isConverting; + + void doSeparate(const TFilePath& source, int from, int to, int framerate, + FrameTaskNotifier* frameNotifier, bool do4Colors); + + void doCompute(TRaster32P raster, TDimensionI& dim, TRaster32P ras_m, + TRaster32P ras_c1, TRaster32P ras_c2, bool isPreview = false); + + void doCompute(TRaster32P raster, TDimensionI& dim, TRaster32P ras_m, + TRaster32P ras_c1, TRaster32P ras_c2, TRaster32P ras_c3, + bool isPreview = false); + + void doPreview(TRaster32P& orgRas, TRaster32P& mainRas, TRaster32P& sub1Ras, + TRaster32P& sub2Ras, TRaster32P& sub3Ras); + +public: + SeparateColorsPopup(); + ~SeparateColorsPopup(); + void setFiles(const std::vector& fps); + bool isConverting(); + +protected: + void showEvent(QShowEvent* e); + // store the current value to user env file + void hideEvent(QHideEvent* e); + +public slots: + // starts the convertion + void separate(); + void onSeparateFinished(); + void onPreviewBtnPressed(); + void onPreviewFrameFieldValueChanged(bool isDragging); + + void onChange(bool isDragging); + void onToggle() { onChange(false); } + void onColorChange(const TPixel32&, bool isDragging) { onChange(isDragging); } +}; + +#endif \ No newline at end of file diff --git a/toonz/sources/toonz/separatecolorsswatch.cpp b/toonz/sources/toonz/separatecolorsswatch.cpp new file mode 100644 index 0000000..d02e21a --- /dev/null +++ b/toonz/sources/toonz/separatecolorsswatch.cpp @@ -0,0 +1,473 @@ +#include "separatecolorsswatch.h" + +#include "tapp.h" + +#include "toonzqt/styleeditor.h" +#include "toonzqt/menubarcommand.h" +#include "toonzqt/viewcommandids.h" +#include "toonzqt/gutil.h" +#include "toonzqt/dvdialog.h" + +#include "toonz/tcleanupper.h" + +#include "tools/stylepicker.h" +#include "tools/toolcommandids.h" + +#include "trasterimage.h" +#include "tpixelutils.h" +#include "trop.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------- +namespace { +#define ZOOMLEVELS 33 +#define NOZOOMINDEX 20 +double ZoomFactors[ZOOMLEVELS] = { + 0.001, 0.002, 0.003, 0.004, 0.005, 0.007, 0.01, 0.015, 0.02, 0.03, 0.04, + 0.05, 0.0625, 0.0833, 0.125, 0.167, 0.25, 0.333, 0.5, 0.667, 1, 2, + 3, 4, 5, 6, 7, 8, 12, 16, 24, 32, 40}; + +double getQuantizedZoomFactor(double zf, bool forward) { + if (forward && (zf > ZoomFactors[ZOOMLEVELS - 1] || + areAlmostEqual(zf, ZoomFactors[ZOOMLEVELS - 1], 1e-5))) + return zf; + else if (!forward && + (zf < ZoomFactors[0] || areAlmostEqual(zf, ZoomFactors[0], 1e-5))) + return zf; + + assert((!forward && zf > ZoomFactors[0]) || + (forward && zf < ZoomFactors[ZOOMLEVELS - 1])); + int i = 0; + for (i = 0; i <= ZOOMLEVELS - 1; i++) + if (areAlmostEqual(zf, ZoomFactors[i], 1e-5)) zf = ZoomFactors[i]; + + if (forward && zf < ZoomFactors[0]) + return ZoomFactors[0]; + else if (!forward && zf > ZoomFactors[ZOOMLEVELS - 1]) + return ZoomFactors[ZOOMLEVELS - 1]; + + for (i = 0; i < ZOOMLEVELS - 1; i++) + if (ZoomFactors[i + 1] - zf >= 0 && zf - ZoomFactors[i] >= 0) { + if (forward && ZoomFactors[i + 1] == zf) + return ZoomFactors[i + 2]; + else if (!forward && ZoomFactors[i] == zf) + return ZoomFactors[i - 1]; + else + return forward ? ZoomFactors[i + 1] : ZoomFactors[i]; + } + return ZoomFactors[NOZOOMINDEX]; +} + +} // namespace +//------------------------------------------------------------------- + +SeparateSwatchArea::SeparateSwatchArea(SeparateSwatch *parent, SWATCH_TYPE type) + : QWidget(parent) + , m_type(type) + , m_sw(parent) + , m_transparentColor(64, 64, 64) { + setMinimumHeight(100); + + // The following helps in re-establishing focus for wheel events + setFocusPolicy(Qt::WheelFocus); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +} + +//------------------------------------------------------------------- + +void SeparateSwatchArea::mousePressEvent(QMouseEvent *event) { + if (!m_sw->m_mainRaster || m_sw->m_lx == 0 || m_sw->m_ly == 0) return; + + m_pos = event->pos(); + + // return if there is no raster + if (!m_r) { + event->ignore(); + m_panning = false; + return; + } + + // panning with drag + m_panning = true; + + event->ignore(); +} + +//----------------------------------------------------------------------------- + +void SeparateSwatchArea::keyPressEvent(QKeyEvent *event) { + if (!m_sw->m_mainRaster || m_sw->m_lx == 0 || m_sw->m_ly == 0) return; + + QString zoomInTxt = + CommandManager::instance()->getAction(V_ZoomIn)->shortcut().toString(); + QString zoomOutTxt = + CommandManager::instance()->getAction(V_ZoomOut)->shortcut().toString(); + + bool isZoomIn = + (QString::compare(event->text(), zoomInTxt, Qt::CaseInsensitive) == 0); + bool isZoomOut = + (QString::compare(event->text(), zoomOutTxt, Qt::CaseInsensitive) == 0); + + int key = event->key(); + + if (key != '+' && key != '-' && key != '0' && !isZoomIn && !isZoomOut) return; + + bool reset = (key == '0'); + bool forward = (key == '+' || isZoomIn); + + double currZoomScale = sqrt(m_sw->m_viewAff.det()); + double factor = reset ? 1 : getQuantizedZoomFactor(currZoomScale, forward); + + double minZoom = std::min((double)m_sw->m_lx / m_sw->m_mainRaster->getLx(), + (double)m_sw->m_ly / m_sw->m_mainRaster->getLy()); + if ((!forward && factor < minZoom) || (forward && factor > 40.0)) return; + + TPointD delta(0.5 * width(), 0.5 * height()); + m_sw->m_viewAff = (TTranslation(delta) * TScale(factor / currZoomScale) * + TTranslation(-delta)) * + m_sw->m_viewAff; + + m_sw->m_orgSwatch->updateRaster(); + m_sw->m_mainSwatch->updateRaster(); + m_sw->m_sub1Swatch->updateRaster(); + m_sw->m_sub2Swatch->updateRaster(); + m_sw->m_sub3Swatch->updateRaster(); +} + +//----------------------------------------------------------------------------- +void SeparateSwatchArea::mouseReleaseEvent(QMouseEvent *event) { + m_sw->m_mainSwatch->updateRaster(); + m_sw->m_sub1Swatch->updateRaster(); + m_sw->m_sub2Swatch->updateRaster(); + m_sw->m_sub3Swatch->updateRaster(); + m_panning = false; +} + +//---------------------------------------------------------------- +void SeparateSwatchArea::mouseMoveEvent(QMouseEvent *event) { + if (!m_panning) return; + + TPoint curPos = TPoint(event->pos().x(), event->pos().y()); + + QPoint delta = event->pos() - m_pos; + if (delta == QPoint()) return; + TAffine oldAff = m_sw->m_viewAff; + m_sw->m_viewAff = TTranslation(delta.x(), -delta.y()) * m_sw->m_viewAff; + + m_sw->m_orgSwatch->updateRaster(); + m_sw->m_mainSwatch->updateRaster(true); + m_sw->m_sub1Swatch->updateRaster(true); + m_sw->m_sub2Swatch->updateRaster(true); + m_sw->m_sub3Swatch->updateRaster(true); + + m_pos = event->pos(); +} + +//--------------------------------------------------------------- + +void SeparateSwatchArea::updateSeparated(bool dragging) { + TAffine aff = getFinalAff(); + + TRect rectToCompute = convert(aff.inv() * convert(m_r->getBounds())); + TRect outRect = m_sw->m_mainRaster->getBounds() * rectToCompute; + + if (outRect.isEmpty()) return; +} + +//--------------------------------------------------------------------------------- + +TAffine SeparateSwatchArea::getFinalAff() { + return m_sw->m_viewAff * + TAffine().place(m_sw->m_mainRaster->getCenterD(), m_r->getCenterD()); +} + +//------------------------------------------------------------------------------ +void SeparateSwatchArea::updateRaster(bool dragging) { + if (isHidden() || m_sw->m_lx == 0 || m_sw->m_ly == 0) return; + + if (!m_r || m_r->getLx() != m_sw->m_lx || m_r->getLy() != m_sw->m_ly) + m_r = TRaster32P(m_sw->m_lx, m_sw->m_ly); + + if (!m_sw->m_mainRaster) + m_r->fill(TPixel(200, 200, 200)); + else { + m_r->fill(m_transparentColor); + switch (m_type) { + case Original: + TRop::quickPut(m_r, m_sw->m_orgRaster, getFinalAff()); + break; + case Main: + TRop::quickPut(m_r, m_sw->m_mainRaster, getFinalAff()); + break; + case Sub1: + TRop::quickPut(m_r, m_sw->m_sub1Raster, getFinalAff()); + break; + case Sub2: + TRop::quickPut(m_r, m_sw->m_sub2Raster, getFinalAff()); + break; + case Sub3: + TRop::quickPut(m_r, m_sw->m_sub3Raster, getFinalAff()); + break; + } + } + if (dragging) + repaint(); + else + update(); +} + +//---------------------------------------------------------------------------------- + +void SeparateSwatchArea::paintEvent(QPaintEvent *event) { + QPainter p(this); + if (!m_r) + p.fillRect(rect(), QBrush(QColor(200, 200, 200))); + else + p.drawImage(rect(), rasterToQImage(m_r)); +} + +//----------------------------------------------------------------- + +void SeparateSwatchArea::wheelEvent(QWheelEvent *event) { + if (!m_sw->m_mainSwatch || m_sw->m_lx == 0 || m_sw->m_ly == 0) return; + + int step = event->delta() > 0 ? 120 : -120; + double factor = exp(0.001 * step); + if (factor == 1.0) return; + double scale = m_sw->m_viewAff.det(); + double minZoom = std::min((double)m_sw->m_lx / m_sw->m_mainRaster->getLx(), + (double)m_sw->m_ly / m_sw->m_mainRaster->getLy()); + if ((factor < 1 && sqrt(scale) < minZoom) || (factor > 1 && scale > 1200.0)) + return; + + TPointD delta(event->pos().x(), height() - event->pos().y()); + m_sw->m_viewAff = + (TTranslation(delta) * TScale(factor) * TTranslation(-delta)) * + m_sw->m_viewAff; + + m_sw->m_orgSwatch->updateRaster(); + m_sw->m_mainSwatch->updateRaster(); + m_sw->m_sub1Swatch->updateRaster(); + m_sw->m_sub2Swatch->updateRaster(); + m_sw->m_sub3Swatch->updateRaster(); +} + +//------------------------------------------------------------------------------- +void SeparateSwatchArea::setTranspColor(TPixel32 &lineColor, bool showAlpha) { + if (showAlpha) { + m_transparentColor = TPixel32::Black; + return; + } + + TPixelD lineColorD = toPixelD(lineColor); + double h, l, s; + rgb2hls(lineColorD.r, lineColorD.g, lineColorD.b, &h, &l, &s); + // if the specified color is reddish, use blue color for transparent area + if (l < 0.8) + m_transparentColor = TPixel32::White; + else + m_transparentColor = TPixel32(64, 64, 64); +} + +//------------------------------------------------------------------------------- +// focus on mouse enter + +void SeparateSwatchArea::enterEvent(QEvent *event) { + setFocus(); + event->accept(); +} + +//===================================================================== + +SeparateSwatch::SeparateSwatch(QWidget *parent, int lx, int ly) + : QWidget(parent), m_lx(lx), m_ly(ly), m_enabled(false), m_viewAff() { + m_orgSwatch = new SeparateSwatchArea(this, Original); + m_mainSwatch = new SeparateSwatchArea(this, Main); + m_sub1Swatch = new SeparateSwatchArea(this, Sub1); + m_sub2Swatch = new SeparateSwatchArea(this, Sub2); + m_sub3Swatch = new SeparateSwatchArea(this, Sub3); + + m_sub3Label = new QLabel(tr("Sub Color 3"), this); + + QGridLayout *mainLay = new QGridLayout(); + mainLay->setHorizontalSpacing(2); + mainLay->setVerticalSpacing(2); + { + mainLay->addWidget(new QLabel(tr("Original"), this), 0, 0); + mainLay->addWidget(new QLabel(tr("Main Color"), this), 0, 1); + + mainLay->addWidget(m_orgSwatch, 1, 0); + mainLay->addWidget(m_mainSwatch, 1, 1); + + mainLay->addWidget(new QLabel(tr("Sub Color 1"), this), 2, 0); + mainLay->addWidget(new QLabel(tr("Sub Color 2"), this), 2, 1); + mainLay->addWidget(m_sub3Label, 2, 2); + + mainLay->addWidget(m_sub1Swatch, 3, 0); + mainLay->addWidget(m_sub2Swatch, 3, 1); + mainLay->addWidget(m_sub3Swatch, 3, 2); + } + mainLay->setRowStretch(0, 0); + mainLay->setRowStretch(1, 1); + mainLay->setRowStretch(2, 0); + mainLay->setRowStretch(3, 1); + setLayout(mainLay); + + m_sub3Swatch->setVisible(false); + m_sub3Label->setVisible(false); +} + +//--------------------------------------------------------------------- + +void SeparateSwatch::enable(bool state) { + m_enabled = state; + if (!m_enabled) { + m_orgRaster = TRasterP(); + m_mainRaster = TRasterP(); + m_sub1Raster = TRasterP(); + m_sub2Raster = TRasterP(); + m_sub3Raster = TRasterP(); + + m_viewAff = TAffine(); + + m_orgSwatch->updateRaster(); + m_mainSwatch->updateRaster(); + m_sub1Swatch->updateRaster(); + m_sub2Swatch->updateRaster(); + m_sub3Swatch->updateRaster(); + } +} + +//---------------------------------------------------------------- + +void SeparateSwatch::resizeEvent(QResizeEvent *event) { + QSize s = m_orgSwatch->size(); + m_lx = s.width(); + m_ly = s.height(); + + m_orgSwatch->setMinimumHeight(0); + m_mainSwatch->setMinimumHeight(0); + m_sub1Swatch->setMinimumHeight(0); + m_sub2Swatch->setMinimumHeight(0); + m_sub3Swatch->setMinimumHeight(0); + + m_orgSwatch->updateRaster(); + m_mainSwatch->updateRaster(); + m_sub1Swatch->updateRaster(); + m_sub2Swatch->updateRaster(); + m_sub3Swatch->updateRaster(); + + QWidget::resizeEvent(event); +} + +//--------------------------------------------------- + +bool SeparateSwatch::isEnabled() { return isVisible() && m_enabled; } + +//------------------------------------------------------------ +void SeparateSwatch::setRaster(TRasterP orgRas, TRasterP mainRas, + TRasterP sub1Ras, TRasterP sub2Ras) { + m_sub3Swatch->setVisible(false); + m_sub3Label->setVisible(false); + + if (!isVisible()) { + m_orgRaster = TRasterP(); + m_mainRaster = TRasterP(); + m_sub1Raster = TRasterP(); + m_sub2Raster = TRasterP(); + return; + } + + // obtain the size here in order to avoid the image shrink + // when activating / deactivating sub3 color. + qApp->processEvents(); + QSize s = m_orgSwatch->size(); + m_lx = s.width(); + m_ly = s.height(); + + m_orgRaster = orgRas; + m_mainRaster = mainRas; + m_sub1Raster = sub1Ras; + m_sub2Raster = sub2Ras; + + m_orgSwatch->updateRaster(); + m_mainSwatch->updateRaster(); + m_sub1Swatch->updateRaster(); + m_sub2Swatch->updateRaster(); +} + +//------------------------------------------------------------ +// 4 colors version + +void SeparateSwatch::setRaster(TRasterP orgRas, TRasterP mainRas, + TRasterP sub1Ras, TRasterP sub2Ras, + TRasterP sub3Ras) { + //�o�� + m_sub3Swatch->setVisible(true); + m_sub3Label->setVisible(true); + + if (!isVisible()) { + m_orgRaster = TRasterP(); + m_mainRaster = TRasterP(); + m_sub1Raster = TRasterP(); + m_sub2Raster = TRasterP(); + m_sub3Raster = TRasterP(); + return; + } + + // obtain the size here in order to avoid the image shrink + // when activating / deactivating sub3 color. + qApp->processEvents(); + QSize s = m_orgSwatch->size(); + m_lx = s.width(); + m_ly = s.height(); + + m_orgRaster = orgRas; + m_mainRaster = mainRas; + m_sub1Raster = sub1Ras; + m_sub2Raster = sub2Ras; + m_sub3Raster = sub3Ras; + + m_orgSwatch->updateRaster(); + m_mainSwatch->updateRaster(); + m_sub1Swatch->updateRaster(); + m_sub2Swatch->updateRaster(); + m_sub3Swatch->updateRaster(); +} + +//-------------------------------------------------------------------- + +void SeparateSwatch::updateSeparated() { + m_mainSwatch->updateRaster(); + m_sub1Swatch->updateRaster(); + m_sub2Swatch->updateRaster(); + m_sub3Swatch->updateRaster(); +} + +//-------------------------------------------------------------------- + +void SeparateSwatch::setTranspColors(TPixel32 &mainCol, TPixel32 &sub1Col, + TPixel32 &sub2Col, TPixel32 &sub3Col, + bool showAlpha) { + m_mainSwatch->setTranspColor(mainCol, showAlpha); + m_sub1Swatch->setTranspColor(sub1Col, showAlpha); + m_sub2Swatch->setTranspColor(sub2Col, showAlpha); + m_sub3Swatch->setTranspColor(sub3Col, showAlpha); +} + +//-------------------------------------------------------------------- +void SeparateSwatch::showSub3Swatch(bool on) { + setRaster(TRasterP(), TRasterP(), TRasterP(), TRasterP(), TRasterP()); + + m_sub3Swatch->setVisible(on); + m_sub3Label->setVisible(on); +} \ No newline at end of file diff --git a/toonz/sources/toonz/separatecolorsswatch.h b/toonz/sources/toonz/separatecolorsswatch.h new file mode 100644 index 0000000..b25fc8d --- /dev/null +++ b/toonz/sources/toonz/separatecolorsswatch.h @@ -0,0 +1,86 @@ +#pragma once +#ifndef SEPARATECOLORSSWATCH_H +#define SEPARATECOLORSSWATCH_H + +#include "traster.h" +#include + +class QAction; +class QLabel; + +enum SWATCH_TYPE { Original, Main, Sub1, Sub2, Sub3 }; + +class SeparateSwatch; + +class SeparateSwatchArea : public QWidget { + Q_OBJECT + QPoint m_pos; + SWATCH_TYPE m_type; + bool m_panning; + SeparateSwatch* m_sw; + TRaster32P m_r; + TAffine getFinalAff(); + + TPixel32 m_transparentColor; + +public: + SeparateSwatchArea(SeparateSwatch* parent, SWATCH_TYPE type); + void updateRaster(bool dragging = false); + void updateSeparated(bool dragging = false); + void setTranspColor(TPixel32& lineColor, bool showAlpha = false); + +protected: + void paintEvent(QPaintEvent* event); + void mousePressEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); + void wheelEvent(QWheelEvent* event); + void keyPressEvent(QKeyEvent* event); + // focus on mouse enter + void enterEvent(QEvent* event); +}; + +class SeparateSwatch : public QWidget { + Q_OBJECT + +public: + int m_lx, m_ly; + bool m_enabled; + SeparateSwatchArea* m_orgSwatch; + SeparateSwatchArea* m_mainSwatch; + SeparateSwatchArea* m_sub1Swatch; + SeparateSwatchArea* m_sub2Swatch; + SeparateSwatchArea* m_sub3Swatch; + + QLabel* m_sub3Label; + + TAffine m_viewAff; + TRasterP m_orgRaster; + TRasterP m_mainRaster; + TRasterP m_sub1Raster; + TRasterP m_sub2Raster; + TRasterP m_sub3Raster; + + SeparateSwatch(QWidget* parent, int lx, int ly); + + void setRaster(TRasterP orgRas, TRasterP mainRas, TRasterP sub1Ras, + TRasterP sub2Ras); + void setRaster(TRasterP orgRas, TRasterP mainRas, TRasterP sub1Ras, + TRasterP sub2Ras, TRasterP sub3Ras); + void updateSeparated(); + bool isEnabled(); + void enable(bool state); + void setTranspColors(TPixel32& mainCol, TPixel32& sub1Col, TPixel32& sub2Col, + TPixel32& sub3Col, bool showAlpha = false); + +protected: + void resizeEvent(QResizeEvent* event); + +protected slots: + void showSub3Swatch(bool); + +signals: + void enabled(); +}; + +#endif \ No newline at end of file diff --git a/toonz/sources/toonz/shifttracetool.cpp b/toonz/sources/toonz/shifttracetool.cpp deleted file mode 100644 index 96c54b7..0000000 --- a/toonz/sources/toonz/shifttracetool.cpp +++ /dev/null @@ -1,552 +0,0 @@ - - -#include "shifttracetool.h" -#include "toonz/onionskinmask.h" -#include "toonz/tonionskinmaskhandle.h" -#include "tools/cursors.h" -#include "tools/tool.h" -#include "timage.h" -#include "trasterimage.h" -#include "ttoonzimage.h" -#include "tvectorimage.h" -#include "toonz/txsheet.h" -#include "toonz/txshcell.h" -#include "toonz/txsheethandle.h" -#include "toonz/tframehandle.h" -#include "toonz/tcolumnhandle.h" -#include "toonz/dpiscale.h" -#include "tapp.h" -#include "tpixel.h" -#include "toonzqt/menubarcommand.h" - -#include "tgl.h" -#include - -//============================================================================= - -static bool circumCenter(TPointD &out, const TPointD &a, const TPointD &b, - const TPointD &c) { - double d = 2 * (a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)); - if (fabs(d) < 0.0001) { - out = TPointD(); - return false; - } - out.x = ((a.y * a.y + a.x * a.x) * (b.y - c.y) + - (b.y * b.y + b.x * b.x) * (c.y - a.y) + - (c.y * c.y + c.x * c.x) * (a.y - b.y)) / - d; - out.y = ((a.y * a.y + a.x * a.x) * (c.x - b.x) + - (b.y * b.y + b.x * b.x) * (a.x - c.x) + - (c.y * c.y + c.x * c.x) * (b.x - a.x)) / - d; - return true; -} - -//============================================================================= - -class ShiftTraceTool final : public TTool { -public: - enum CurveStatus { - NoCurve, - TwoPointsCurve, // just during the first click&drag - ThreePointsCurve - }; - - enum GadgetId { - NoGadget, - CurveP0Gadget, - CurveP1Gadget, - CurvePmGadget, - MoveCenterGadget, - RotateGadget, - TranslateGadget - }; - inline bool isCurveGadget(GadgetId id) const { - return CurveP0Gadget <= id && id <= CurvePmGadget; - } - -private: - TPointD m_oldPos, m_startPos; - int m_ghostIndex; - TPointD m_p0, m_p1, m_p2; - - CurveStatus m_curveStatus; - GadgetId m_gadget; - GadgetId m_highlightedGadget; - - TRectD m_box; - TAffine m_dpiAff; - int m_row[2]; - TAffine m_aff[2]; - TPointD m_center[2]; - -public: - ShiftTraceTool(); - - ToolType getToolType() const override { return GenericTool; } - - void clearData(); - void updateData(); - void updateBox(); - void updateCurveAffs(); - void updateGhost(); - - void reset() override { - onActivate(); - invalidate(); - } - - void mouseMove(const TPointD &, const TMouseEvent &e) override; - void leftButtonDown(const TPointD &, const TMouseEvent &) override; - void leftButtonDrag(const TPointD &, const TMouseEvent &) override; - void leftButtonUp(const TPointD &, const TMouseEvent &) override; - void draw() override; - - TAffine getGhostAff(); - GadgetId getGadget(const TPointD &); - void drawDot(const TPointD ¢er, double r, - const TPixel32 &color = TPixel32::White); - void drawControlRect(); - void drawCurve(); - - void onActivate() override { - m_ghostIndex = 0; - m_curveStatus = NoCurve; - clearData(); - OnionSkinMask osm = - TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask(); - m_aff[0] = osm.getShiftTraceGhostAff(0); - m_aff[1] = osm.getShiftTraceGhostAff(1); - m_center[0] = osm.getShiftTraceGhostCenter(0); - m_center[1] = osm.getShiftTraceGhostCenter(1); - } - void onDeactivate() override { - QAction *action = CommandManager::instance()->getAction("MI_EditShift"); - action->setChecked(false); - } - - int getCursorId() const override; -}; - -ShiftTraceTool::ShiftTraceTool() - : TTool("T_ShiftTrace") - , m_ghostIndex(0) - , m_curveStatus(NoCurve) - , m_gadget(NoGadget) - , m_highlightedGadget(NoGadget) { - bind(TTool::AllTargets); // Deals with tool deactivation internally -} - -void ShiftTraceTool::clearData() { - m_ghostIndex = 0; - m_curveStatus = NoCurve; - m_gadget = NoGadget; - m_highlightedGadget = NoGadget; - - m_box = TRectD(); - for (int i = 0; i < 2; i++) { - m_row[i] = -1; - m_aff[i] = TAffine(); - m_center[i] = TPointD(); - } -} - -void ShiftTraceTool::updateBox() { - if (0 <= m_ghostIndex && m_ghostIndex < 2 && m_row[m_ghostIndex] >= 0) { - int col = TApp::instance()->getCurrentColumn()->getColumnIndex(); - int row = m_row[m_ghostIndex]; - TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); - - TXshCell cell = xsh->getCell(row, col); - TXshSimpleLevel *sl = cell.getSimpleLevel(); - if (sl) { - m_dpiAff = getDpiAffine(sl, cell.m_frameId); - TImageP img = cell.getImage(false); - if (img) { - if (TRasterImageP ri = img) { - TRasterP ras = ri->getRaster(); - m_box = (convert(ras->getBounds()) - ras->getCenterD()) * - ri->getSubsampling(); - } else if (TToonzImageP ti = img) { - TRasterP ras = ti->getRaster(); - m_box = (convert(ras->getBounds()) - ras->getCenterD()) * - ti->getSubsampling(); - } else if (TVectorImageP vi = img) { - m_box = vi->getBBox(); - } - } - } - } -} - -void ShiftTraceTool::updateData() { - TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); - int row = TApp::instance()->getCurrentFrame()->getFrame(); - int col = TApp::instance()->getCurrentColumn()->getColumnIndex(); - TXshCell cell = xsh->getCell(row, col); - m_box = TRectD(); - for (int i = 0; i < 2; i++) m_row[i] = -1; - m_dpiAff = TAffine(); - - // we must find the prev (m_row[0]) and next (m_row[1]) reference images - // (either might not exist) - // see also stage.cpp, StageBuilder::addCellWithOnionSkin - - if (cell.isEmpty()) { - // current cell is empty. search for the prev ref img - int r = row - 1; - while (r >= 0 && xsh->getCell(r, col).getSimpleLevel() == 0) r--; - if (r >= 0) m_row[0] = r; - // else prev drawing doesn't exist : nothing to do - } else { - // current cell is not empty - // search for prev ref img - TXshSimpleLevel *sl = cell.getSimpleLevel(); - int r = row - 1; - if (r >= 0) { - TXshCell otherCell = xsh->getCell(r, col); - if (otherCell.getSimpleLevel() == sl) { - // find the span start - while (r - 1 >= 0 && xsh->getCell(r - 1, col) == otherCell) r--; - m_row[0] = r; - } - } - - // search for next ref img - r = row + 1; - while (xsh->getCell(r, col) == cell) r++; - // first cell after the current span has the same level - if (xsh->getCell(r, col).getSimpleLevel() == sl) m_row[1] = r; - } - updateBox(); -} - -// -// Compute m_aff[0] and m_aff[1] according to the current curve -// -void ShiftTraceTool::updateCurveAffs() { - if (m_curveStatus != ThreePointsCurve) { - m_aff[0] = m_aff[1] = TAffine(); - } else { - double phi0 = 0, phi1 = 0; - TPointD center; - if (circumCenter(center, m_p0, m_p1, m_p2)) { - TPointD v0 = normalize(m_p0 - center); - TPointD v1 = normalize(m_p1 - center); - TPointD v2 = normalize(m_p2 - center); - TPointD u0(-v0.y, v0.x); - TPointD u1(-v1.y, v1.x); - phi0 = atan2((v2 * u0), (v2 * v0)) * 180.0 / 3.1415; - phi1 = atan2((v2 * u1), (v2 * v1)) * 180.0 / 3.1415; - } - m_aff[0] = TTranslation(m_p2 - m_p0) * TRotation(m_p0, phi0); - m_aff[1] = TTranslation(m_p2 - m_p1) * TRotation(m_p1, phi1); - } -} - -void ShiftTraceTool::updateGhost() { - OnionSkinMask osm = - TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask(); - osm.setShiftTraceGhostAff(0, m_aff[0]); - osm.setShiftTraceGhostAff(1, m_aff[1]); - osm.setShiftTraceGhostCenter(0, m_center[0]); - osm.setShiftTraceGhostCenter(1, m_center[1]); - TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(osm); -} - -TAffine ShiftTraceTool::getGhostAff() { - if (0 <= m_ghostIndex && m_ghostIndex < 2) - return m_aff[m_ghostIndex] * m_dpiAff; - else - return TAffine(); -} - -void ShiftTraceTool::drawDot(const TPointD ¢er, double r, - const TPixel32 &color) { - tglColor(color); - tglDrawDisk(center, r); - glColor3d(0.2, 0.2, 0.2); - tglDrawCircle(center, r); -} - -void ShiftTraceTool::drawControlRect() { - if (m_ghostIndex < 0 || m_ghostIndex > 1) return; - int row = m_row[m_ghostIndex]; - if (row < 0) return; - int col = TApp::instance()->getCurrentColumn()->getColumnIndex(); - TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); - TXshCell cell = xsh->getCell(row, col); - if (cell.isEmpty()) return; - TImageP img = cell.getImage(false); - if (!img) return; - TRectD box; - if (TRasterImageP ri = img) { - TRasterP ras = ri->getRaster(); - box = - (convert(ras->getBounds()) - ras->getCenterD()) * ri->getSubsampling(); - } else if (TToonzImageP ti = img) { - TRasterP ras = ti->getRaster(); - box = - (convert(ras->getBounds()) - ras->getCenterD()) * ti->getSubsampling(); - } else if (TVectorImageP vi = img) { - box = vi->getBBox(); - } else { - return; - } - glPushMatrix(); - tglMultMatrix(getGhostAff()); - TPixel32 color; - color = m_highlightedGadget == TranslateGadget ? TPixel32(200, 100, 100) - : TPixel32(120, 120, 120); - tglColor(color); - glBegin(GL_LINE_STRIP); - glVertex2d(box.x0, box.y0); - glVertex2d(box.x1, box.y0); - glVertex2d(box.x1, box.y1); - glVertex2d(box.x0, box.y1); - glVertex2d(box.x0, box.y0); - glEnd(); - color = - m_highlightedGadget == 2000 ? TPixel32(200, 100, 100) : TPixel32::White; - double r = 4 * sqrt(tglGetPixelSize2()); - drawDot(box.getP00(), r, color); - drawDot(box.getP01(), r, color); - drawDot(box.getP10(), r, color); - drawDot(box.getP11(), r, color); - if (m_curveStatus == NoCurve) { - color = - m_highlightedGadget == 2001 ? TPixel32(200, 100, 100) : TPixel32::White; - TPointD c = m_center[m_ghostIndex]; - drawDot(c, r, color); - } - glPopMatrix(); -} - -void ShiftTraceTool::drawCurve() { - if (m_curveStatus == NoCurve) return; - double r = 4 * sqrt(tglGetPixelSize2()); - double u = getPixelSize(); - if (m_curveStatus == TwoPointsCurve) { - TPixel32 color = - m_highlightedGadget == 1000 ? TPixel32(200, 100, 100) : TPixel32::White; - drawDot(m_p0, r, color); - glColor3d(0.2, 0.2, 0.2); - tglDrawSegment(m_p0, m_p1); - drawDot(m_p1, r, TPixel32::Red); - } else if (m_curveStatus == ThreePointsCurve) { - TPixel32 color = - m_highlightedGadget == 1000 ? TPixel32(200, 100, 100) : TPixel32::White; - drawDot(m_p0, r, color); - color = - m_highlightedGadget == 1001 ? TPixel32(200, 100, 100) : TPixel32::White; - drawDot(m_p1, r, color); - - glColor3d(0.2, 0.2, 0.2); - - TPointD center; - if (circumCenter(center, m_p0, m_p1, m_p2)) { - double radius = norm(center - m_p1); - glBegin(GL_LINE_STRIP); - int n = 100; - for (int i = 0; i < n; i++) { - double t = (double)i / n; - TPointD p = (1 - t) * m_p0 + t * m_p2; - p = center + radius * normalize(p - center); - tglVertex(p); - } - for (int i = 0; i < n; i++) { - double t = (double)i / n; - TPointD p = (1 - t) * m_p2 + t * m_p1; - p = center + radius * normalize(p - center); - tglVertex(p); - } - glEnd(); - } else { - tglDrawSegment(m_p0, m_p1); - } - color = - m_highlightedGadget == 1002 ? TPixel32(200, 100, 100) : TPixel32::White; - drawDot(m_p2, r, color); - } -} - -ShiftTraceTool::GadgetId ShiftTraceTool::getGadget(const TPointD &p) { - std::vector> gadgets; - gadgets.push_back(std::make_pair(m_p0, CurveP0Gadget)); - gadgets.push_back(std::make_pair(m_p1, CurveP1Gadget)); - gadgets.push_back(std::make_pair(m_p2, CurvePmGadget)); - TAffine aff = getGhostAff(); - if (0 <= m_ghostIndex && m_ghostIndex < 2) { - gadgets.push_back(std::make_pair(aff * m_box.getP00(), RotateGadget)); - gadgets.push_back(std::make_pair(aff * m_box.getP01(), RotateGadget)); - gadgets.push_back(std::make_pair(aff * m_box.getP10(), RotateGadget)); - gadgets.push_back(std::make_pair(aff * m_box.getP11(), RotateGadget)); - gadgets.push_back( - std::make_pair(aff * m_center[m_ghostIndex], MoveCenterGadget)); - } - int k = -1; - double minDist2 = pow(10 * getPixelSize(), 2); - for (int i = 0; i < (int)gadgets.size(); i++) { - double d2 = norm2(gadgets[i].first - p); - if (d2 < minDist2) { - minDist2 = d2; - k = i; - } - } - if (k >= 0) return gadgets[k].second; - - // rect-point - if (0 <= m_ghostIndex && m_ghostIndex < 2) { - TPointD q = aff.inv() * p; - - double big = 1.0e6; - double d = big, x = 0, y = 0; - if (m_box.x0 < q.x && q.x < m_box.x1) { - x = q.x; - double d0 = fabs(m_box.y0 - q.y); - double d1 = fabs(m_box.y1 - q.y); - if (d0 < d1) { - d = d0; - y = m_box.y0; - } else { - d = d1; - y = m_box.y1; - } - } - if (m_box.y0 < q.y && q.y < m_box.y1) { - double d0 = fabs(m_box.x0 - q.y); - double d1 = fabs(m_box.x1 - q.y); - if (d0 < d) { - d = d0; - y = q.y; - x = m_box.x0; - } - if (d1 < d) { - d = d1; - y = q.y; - x = m_box.x1; - } - } - if (d < big) { - TPointD pp = aff * TPointD(x, y); - double d = norm(p - pp); - if (d < 10 * getPixelSize()) { - return TranslateGadget; - } - } - } - return NoGadget; -} - -void ShiftTraceTool::mouseMove(const TPointD &pos, const TMouseEvent &e) { - GadgetId highlightedGadget = getGadget(pos); - if (highlightedGadget != m_highlightedGadget) { - m_highlightedGadget = highlightedGadget; - invalidate(); - } -} - -void ShiftTraceTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { - m_gadget = m_highlightedGadget; - m_oldPos = m_startPos = pos; - - if (m_gadget == NoGadget) { - int row = getViewer()->posToRow(e.m_pos, 5 * getPixelSize(), false); - if (row >= 0) { - int currentRow = getFrame(); - int index = -1; - if (m_row[0] >= 0 && row <= currentRow) - index = 0; - else if (m_row[1] >= 0 && row > currentRow) - index = 1; - if (index >= 0) { - m_ghostIndex = index; - updateBox(); - } - } - - if (!e.isCtrlPressed()) { - m_gadget = TranslateGadget; - // m_curveStatus = NoCurve; - } - } - invalidate(); -} - -void ShiftTraceTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &) { - if (m_gadget == NoGadget) { - if (norm(pos - m_oldPos) > 10 * getPixelSize()) { - m_curveStatus = TwoPointsCurve; - m_p0 = m_oldPos; - m_gadget = CurveP1Gadget; - } - } - - if (isCurveGadget(m_gadget)) { - if (m_gadget == CurveP0Gadget) - m_p0 = pos; - else if (m_gadget == CurveP1Gadget) - m_p1 = pos; - else - m_p2 = pos; - updateCurveAffs(); - } else if (m_gadget == RotateGadget) { - TAffine aff = getGhostAff(); - TPointD c = aff * m_center[m_ghostIndex]; - TPointD a = m_oldPos - c; - TPointD b = pos - c; - m_oldPos = pos; - TPointD u = normalize(a); - double phi = - atan2(-u.y * b.x + u.x * b.y, u.x * b.x + u.y * b.y) * 180.0 / 3.14153; - - TPointD imgC = aff * m_center[m_ghostIndex]; - - m_aff[m_ghostIndex] = TRotation(imgC, phi) * m_aff[m_ghostIndex]; - } else if (m_gadget == MoveCenterGadget) { - TAffine aff = getGhostAff().inv(); - TPointD delta = aff * pos - aff * m_oldPos; - m_oldPos = pos; - m_center[m_ghostIndex] += delta; - } else if (m_gadget == TranslateGadget) { - TPointD delta = pos - m_oldPos; - m_oldPos = pos; - m_aff[m_ghostIndex] = TTranslation(delta) * m_aff[m_ghostIndex]; - } - - updateGhost(); - invalidate(); -} - -void ShiftTraceTool::leftButtonUp(const TPointD &pos, const TMouseEvent &) { - if (CurveP0Gadget <= m_gadget && m_gadget <= CurvePmGadget) { - if (m_curveStatus == TwoPointsCurve) { - m_p2 = (m_p0 + m_p1) * 0.5; - m_curveStatus = ThreePointsCurve; - updateCurveAffs(); - updateGhost(); - - m_center[0] = (m_aff[0] * m_dpiAff).inv() * m_p2; - m_center[1] = (m_aff[1] * m_dpiAff).inv() * m_p2; - } - } - m_gadget = NoGadget; - invalidate(); -} - -void ShiftTraceTool::draw() { - updateData(); - drawControlRect(); - drawCurve(); -} - -int ShiftTraceTool::getCursorId() const { - if (m_highlightedGadget == RotateGadget) - return ToolCursor::RotateCursor; - else if (isCurveGadget(m_highlightedGadget)) - return ToolCursor::PinchCursor; - else - return ToolCursor::MoveCursor; -} - -ShiftTraceTool shiftTraceTool; diff --git a/toonz/sources/toonz/shifttracetool.h b/toonz/sources/toonz/shifttracetool.h deleted file mode 100644 index 6f70f09..0000000 --- a/toonz/sources/toonz/shifttracetool.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/toonz/sources/toonz/shortcutpopup.cpp b/toonz/sources/toonz/shortcutpopup.cpp index 7cc1b55..5022abe 100644 --- a/toonz/sources/toonz/shortcutpopup.cpp +++ b/toonz/sources/toonz/shortcutpopup.cpp @@ -8,7 +8,6 @@ #include "tenv.h" #include "tsystem.h" -#include "toonz/preferences.h" #include "toonz/toonzfolders.h" // TnzQt includes #include "toonzqt/gutil.h" diff --git a/toonz/sources/toonz/svnlockdialog.cpp b/toonz/sources/toonz/svnlockdialog.cpp index 16fd53e..633c770 100644 --- a/toonz/sources/toonz/svnlockdialog.cpp +++ b/toonz/sources/toonz/svnlockdialog.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/toonz/sources/toonz/tapp.h b/toonz/sources/toonz/tapp.h index 2779ee0..ae97c52 100644 --- a/toonz/sources/toonz/tapp.h +++ b/toonz/sources/toonz/tapp.h @@ -81,9 +81,6 @@ class TApp final : public QObject, QMainWindow *m_mainWindow; - // keep a pointer of the inknpaint viewer in order to enable navigator pan in - // the filmstrip - ComboViewerPanel *m_inknPaintViewerPanel; SceneViewer *m_activeViewer; XsheetViewer *m_xsheetViewer; @@ -190,16 +187,11 @@ public: QString getCurrentRoomName() const; - // keep a pointer of the inknpaint viewer in order to enable navigator pan in - // the filmstrip - void setInknPaintViewerPanel(ComboViewerPanel *panel) { - m_inknPaintViewerPanel = panel; + void setActiveViewer(SceneViewer *viewer) { + if (m_activeViewer == viewer) return; + m_activeViewer = viewer; + emit activeViewerChanged(); } - ComboViewerPanel *getInknPaintViewerPanel() const { - return m_inknPaintViewerPanel; - } - - void setActiveViewer(SceneViewer *viewer) { m_activeViewer = viewer; } SceneViewer *getActiveViewer() const { return m_activeViewer; } @@ -254,6 +246,9 @@ signals: // NOTE: For now QEvent::TabletLeaveProximity is NOT detected on Windows. See // QTBUG-53628. void tabletLeft(); + + void + activeViewerChanged(); // TODO: put widgets-related stuffs in some new handle }; #endif // TAPP_H diff --git a/toonz/sources/toonz/toonz.qrc b/toonz/sources/toonz/toonz.qrc index 13c887d..7a2dd82 100644 --- a/toonz/sources/toonz/toonz.qrc +++ b/toonz/sources/toonz/toonz.qrc @@ -465,5 +465,10 @@ Resources/colorchiporder_upleft.svg Resources/timeline2xsheet.svg Resources/xsheet2timeline.svg + Resources/shift_and_trace.svg + Resources/shift_and_trace_edit.svg + Resources/shift_and_trace_reset.svg + Resources/up.svg + Resources/down.svg diff --git a/toonz/sources/toonz/tpanels.cpp b/toonz/sources/toonz/tpanels.cpp index 6092c3c..0f77011 100644 --- a/toonz/sources/toonz/tpanels.cpp +++ b/toonz/sources/toonz/tpanels.cpp @@ -626,6 +626,17 @@ void StudioPaletteViewerPanel::onPaletteSwitched() { m_studioPaletteHandle); } +//----------------------------------------------------------------------------- + +void StudioPaletteViewerPanel::setViewType(int viewType) { + m_studioPaletteViewer->setViewMode(viewType); +} +//----------------------------------------------------------------------------- + +int StudioPaletteViewerPanel::getViewType() { + return m_studioPaletteViewer->getViewMode(); +} + //============================================================================= // StudioPaletteViewerFactory //----------------------------------------------------------------------------- @@ -1264,21 +1275,43 @@ OpenFloatingPanel openLineTestCaptureCommand(MI_OpenLineTestCapture, // ComboViewer : Viewer + Toolbar + Tool Options //----------------------------------------------------------------------------- +ComboViewerPanelContainer::ComboViewerPanelContainer(QWidget *parent) + : StyleShortcutSwitchablePanel(parent) { + m_comboViewer = new ComboViewerPanel(parent); + setFocusProxy(m_comboViewer); + setWidget(m_comboViewer); + + m_comboViewer->initializeTitleBar(getTitleBar()); + bool ret = connect(m_comboViewer->getToolOptions(), SIGNAL(newPanelCreated()), + this, SLOT(updateTabFocus())); + assert(ret); +} +// reimplementation of TPanel::widgetInThisPanelIsFocused +bool ComboViewerPanelContainer::widgetInThisPanelIsFocused() { + return m_comboViewer->hasFocus(); +} +// reimplementation of TPanel::widgetFocusOnEnter +void ComboViewerPanelContainer::widgetFocusOnEnter() { + m_comboViewer->onEnterPanel(); +} +void ComboViewerPanelContainer::widgetClearFocusOnLeave() { + m_comboViewer->onLeavePanel(); +} + +//----------------------------------------------------------------------------- + class ComboViewerFactory final : public TPanelFactory { public: ComboViewerFactory() : TPanelFactory("ComboViewer") {} TPanel *createPanel(QWidget *parent) override { - ComboViewerPanel *panel = new ComboViewerPanel(parent); + ComboViewerPanelContainer *panel = new ComboViewerPanelContainer(parent); panel->setObjectName(getPanelType()); panel->setWindowTitle(QObject::tr("Combo Viewer")); panel->resize(700, 600); return panel; } - void initialize(TPanel *panel) override { - assert(0); - panel->setWidget(new ComboViewerPanel(panel)); - } -} ghibliViewerFactory; + void initialize(TPanel *panel) override { assert(0); } +} comboViewerFactory; //============================================================================= OpenFloatingPanel openComboViewerCommand(MI_OpenComboViewer, "ComboViewer", diff --git a/toonz/sources/toonz/tpanels.h b/toonz/sources/toonz/tpanels.h index db50598..2a0498a 100644 --- a/toonz/sources/toonz/tpanels.h +++ b/toonz/sources/toonz/tpanels.h @@ -24,6 +24,7 @@ class SchematicViewer; class FunctionViewer; class FlipBook; class ToolOptions; +class ComboViewerPanel; //========================================================= // PaletteViewerPanel //--------------------------------------------------------- @@ -69,6 +70,9 @@ class StudioPaletteViewerPanel final : public TPanel { public: StudioPaletteViewerPanel(QWidget *parent); + void setViewType(int viewType) override; + int getViewType() override; + protected: bool isActivatableOnEnter() override { return true; } protected slots: @@ -244,4 +248,23 @@ protected slots: void onMinimizeButtonToggled(bool); }; +//========================================================= +// ComboViewerPanel +//--------------------------------------------------------- + +class ComboViewerPanelContainer final : public StyleShortcutSwitchablePanel { + Q_OBJECT + ComboViewerPanel *m_comboViewer; + +public: + ComboViewerPanelContainer(QWidget *parent); + // reimplementation of TPanel::widgetInThisPanelIsFocused + bool widgetInThisPanelIsFocused() override; + +protected: + // reimplementation of TPanel::widgetFocusOnEnter + void widgetFocusOnEnter() override; + void widgetClearFocusOnLeave() override; +}; + #endif diff --git a/toonz/sources/toonz/versioncontrol.cpp b/toonz/sources/toonz/versioncontrol.cpp index a3fa49a..bf8f4cf 100644 --- a/toonz/sources/toonz/versioncontrol.cpp +++ b/toonz/sources/toonz/versioncontrol.cpp @@ -12,7 +12,6 @@ #include "toonz/txshsimplelevel.h" #include "toonz/txshlevelhandle.h" #include "toonz/txshleveltypes.h" -#include "toonz/txshsimplelevel.h" #include "toonz/palettecontroller.h" #include "toonz/tpalettehandle.h" #include "toonz/tscenehandle.h" diff --git a/toonz/sources/toonz/viewerpane.cpp b/toonz/sources/toonz/viewerpane.cpp index f254fbe..a82f7e7 100644 --- a/toonz/sources/toonz/viewerpane.cpp +++ b/toonz/sources/toonz/viewerpane.cpp @@ -13,7 +13,6 @@ #include "toonz/tframehandle.h" #include "toonz/tcolumnhandle.h" #include "toonz/txshlevelhandle.h" -#include "toonz/txsheethandle.h" #include "toonz/toonzscene.h" #include "toonz/sceneproperties.h" #include "toonz/txsheet.h" diff --git a/toonz/sources/toonz/xshcellmover.cpp b/toonz/sources/toonz/xshcellmover.cpp index a89ce32..6a5858b 100644 --- a/toonz/sources/toonz/xshcellmover.cpp +++ b/toonz/sources/toonz/xshcellmover.cpp @@ -17,7 +17,6 @@ #include "toonzqt/tselectionhandle.h" #include "toonzqt/selection.h" #include "toonzqt/stageobjectsdata.h" -#include "toonzqt/selection.h" #include "historytypes.h" // TnzLib includes @@ -379,7 +378,8 @@ bool LevelMoverTool::isTotallyEmptyColumn(int col) const { TXshColumn *column = xsh->getColumn(col); if (!column) return true; if (!column->isEmpty()) return false; - if (column->getFx()->getOutputConnectionCount() != 0) return false; + TFx *fx = column->getFx(); + if (fx && fx->getOutputConnectionCount() != 0) return false; // bisogna controllare lo stage object return true; } diff --git a/toonz/sources/toonz/xshcellviewer.cpp b/toonz/sources/toonz/xshcellviewer.cpp index 43186cf..4f678d8 100644 --- a/toonz/sources/toonz/xshcellviewer.cpp +++ b/toonz/sources/toonz/xshcellviewer.cpp @@ -137,8 +137,7 @@ bool selectionContainLevelImage(TCellSelection *selection, TXsheet *xsheet) { std::string ext = level->getPath().getType(); int type = level->getType(); - if (type == TZP_XSHLEVEL || type == PLI_XSHLEVEL || - (type == OVL_XSHLEVEL && ext != "psd")) + if (type == TZP_XSHLEVEL || type == PLI_XSHLEVEL || type == OVL_XSHLEVEL) return true; } @@ -803,6 +802,10 @@ void RenameCellField::renameCell() { // if there is no level at the current cell, take the level from the // previous frames // (when editing not empty column) + if (xsheet->isColumnEmpty(c)) { + cells.append(TXshCell()); + continue; + } TXshCell cell; int tmpRow = m_row; @@ -811,9 +814,22 @@ void RenameCellField::renameCell() { if (!cell.isEmpty() || tmpRow == 0) break; tmpRow--; } + + // if the level is not found in the previous frames, then search in the + // following frames + if (cell.isEmpty()) { + tmpRow = m_row + 1; + int maxFrame = xsheet->getFrameCount(); + while (1) { + cell = xsheet->getCell(tmpRow, c); + if (!cell.isEmpty() || tmpRow >= maxFrame) break; + tmpRow++; + } + } + TXshLevel *xl = cell.m_level.getPointer(); - if (!xl || (xl->getType() == OVL_XSHLEVEL && - xl->getPath().getFrame() == TFrameId::NO_FRAME)) { + if (!xl || (xl->getSimpleLevel() && + xl->getSimpleLevel()->getFirstFid() == TFrameId::NO_FRAME)) { cells.append(TXshCell()); continue; } @@ -2282,17 +2298,11 @@ void CellArea::drawKeyframe(QPainter &p, const QRect toBeUpdated) { handleRow1)) { QPoint topLeft = m_viewer->positionToXY(CellPosition(handleRow0, col)); - if (!o->isVerticalTimeline() && - m_viewer->getFrameZoomFactor() <= 50) - topLeft.setY(topLeft.y() - 1); m_viewer->drawPredefinedPath(p, PredefinedPath::BEGIN_EASE_TRIANGLE, topLeft + QPoint(-frameAdj / 2, 0), keyFrameColor, outline); topLeft = m_viewer->positionToXY(CellPosition(handleRow1, col)); - if (!o->isVerticalTimeline() && - m_viewer->getFrameZoomFactor() <= 50) - topLeft.setY(topLeft.y() - 1); m_viewer->drawPredefinedPath(p, PredefinedPath::END_EASE_TRIANGLE, topLeft + QPoint(-frameAdj / 2, 0), keyFrameColor, outline); @@ -2392,13 +2402,6 @@ void CellArea::drawKeyframeLine(QPainter &p, int col, keyRect.center() + m_viewer->positionToXY(CellPosition(rows.from(), col)); QPoint end = keyRect.center() + m_viewer->positionToXY(CellPosition(rows.to(), col)); - - if (!m_viewer->orientation()->isVerticalTimeline() && - m_viewer->getFrameZoomFactor() <= 50) { - begin.setY(begin.y() - 1); - end.setY(end.y() - 1); - } - p.setPen(Qt::white); p.drawLine(QLine(begin, end)); } @@ -2540,6 +2543,56 @@ public: int getHistoryType() override { return HistoryType::Xsheet; } }; //---------------------------------------------------------- +bool CellArea::isKeyFrameArea(int col, int row, QPoint mouseInCell) { + if (!Preferences::instance()->isShowKeyframesOnXsheetCellAreaEnabled()) + return false; + + TXsheet *xsh = m_viewer->getXsheet(); + if (!xsh) return false; + + TStageObject *pegbar = xsh->getStageObject(m_viewer->getObjectId(col)); + int k0, k1; + + bool isKeyframeFrame = pegbar && pegbar->getKeyframeRange(k0, k1) && + (k1 > k0 || k0 == row) && k0 <= row && row <= k1 + 1; + + if (!isKeyframeFrame) return false; + + const Orientation *o = m_viewer->orientation(); + int frameAdj = m_viewer->getFrameZoomAdjustment(); + + if (o->isVerticalTimeline()) + return o->rect(PredefinedRect::KEYFRAME_AREA) + .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) + .contains(mouseInCell) && + row < k1 + 1; + + QRect activeArea = (m_viewer->getFrameZoomFactor() > 50 + ? o->rect(PredefinedRect::KEYFRAME_AREA) + : o->rect(PredefinedRect::FRAME_MARKER_AREA)); + + // If directly over keyframe icon, return true + if (pegbar->isKeyframe(row) && + activeArea.adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) + .contains(mouseInCell) && + row < k1 + 1) + return true; + + // In the white line area, if zoomed in.. narrow height by using frame marker + // area since it has a narrower height + if (m_viewer->getFrameZoomFactor() > 50) + activeArea = o->rect(PredefinedRect::FRAME_MARKER_AREA); + + // Adjust left and/or right edge depending on which part of white line you are + // on + if (row > k0) activeArea.adjust(-activeArea.left(), 0, 0, 0); + if (row < k1) + activeArea.adjust(0, 0, (o->cellWidth() - activeArea.right()), 0); + + return activeArea.adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) + .contains(mouseInCell) && + row < k1 + 1; +} void CellArea::mousePressEvent(QMouseEvent *event) { const Orientation *o = m_viewer->orientation(); @@ -2611,23 +2664,12 @@ void CellArea::mousePressEvent(QMouseEvent *event) { bool isKeyframeFrame = pegbar && pegbar->getKeyframeRange(k0, k1) && (k1 > k0 || k0 == row) && k0 <= row && row <= k1 + 1; - - bool isKeyFrameArea = - isKeyframeFrame && - ((o->isVerticalTimeline() && - o->rect(PredefinedRect::KEYFRAME_AREA) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) - .contains(mouseInCell)) - - || (!o->isVerticalTimeline() && - o->rect(PredefinedRect::FRAME_MARKER_AREA) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) - .contains(mouseInCell))) && - row < k1 + 1; bool accept = false; - if (isKeyFrameArea) { // They are in the keyframe selection - if (pegbar->isKeyframe(row)) // in the keyframe + if (isKeyframeFrame && + isKeyFrameArea(col, row, + mouseInCell)) { // They are in the keyframe selection + if (pegbar->isKeyframe(row)) // in the keyframe { m_viewer->setCurrentRow( row); // If you click on the key, change the current row as well @@ -2779,13 +2821,8 @@ void CellArea::mouseMoveEvent(QMouseEvent *event) { bool isKeyframeFrame = Preferences::instance()->isShowKeyframesOnXsheetCellAreaEnabled() && pegbar && pegbar->getKeyframeRange(k0, k1) && k0 <= row && row <= k1 + 1; - bool isKeyFrameArea = isKeyframeFrame && - o->rect(PredefinedRect::KEYFRAME_AREA) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) - .contains(mouseInCell) && - row < k1 + 1; - if (isKeyFrameArea) { + if (isKeyframeFrame && isKeyFrameArea(col, row, mouseInCell)) { if (pegbar->isKeyframe(row)) // key frame m_tooltip = tr("Click to select keyframe, drag to move it"); else { @@ -2909,14 +2946,8 @@ void CellArea::mouseDoubleClickEvent(QMouseEvent *event) { int k0, k1; bool isKeyframeFrame = pegbar && pegbar->getKeyframeRange(k0, k1) && k0 <= row && row <= k1 + 1; - bool isKeyFrameArea = isKeyframeFrame && - o->rect(PredefinedRect::KEYFRAME_AREA) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) - .contains(mouseInCell) && - row < k1 + 1; - // If you are in the keyframe area, open a function editor - if (isKeyFrameArea) { + if (isKeyframeFrame && isKeyFrameArea(col, row, mouseInCell)) { QAction *action = CommandManager::instance()->getAction(MI_OpenFunctionEditor); action->trigger(); @@ -2979,13 +3010,8 @@ void CellArea::contextMenuEvent(QContextMenuEvent *event) { bool isKeyframeFrame = Preferences::instance()->isShowKeyframesOnXsheetCellAreaEnabled() && pegbar && pegbar->getKeyframeRange(k0, k1) && k0 <= row && row <= k1 + 1; - bool isKeyFrameArea = isKeyframeFrame && - o->rect(PredefinedRect::KEYFRAME_AREA) - .adjusted(-frameAdj / 2, 0, -frameAdj / 2, 0) - .contains(mouseInCell) && - row < k1 + 1; - if (isKeyFrameArea) { + if (isKeyframeFrame && isKeyFrameArea(col, row, mouseInCell)) { TStageObjectId objectId; if (col < 0) objectId = TStageObjectId::CameraId(0); @@ -3029,10 +3055,8 @@ void CellArea::contextMenuEvent(QContextMenuEvent *event) { m_viewer->getCellSelection()->selectCell(row, col); m_viewer->setCurrentColumn(col); } - if (!xsh->getCell(row, col).isEmpty()) - createCellMenu(menu, true, cell); - else - createCellMenu(menu, false, cell); + + createCellMenu(menu, !cell.isEmpty(), cell); } if (!menu.isEmpty()) menu.exec(event->globalPos()); @@ -3122,7 +3146,12 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell) { } if (isCellSelected) { - menu.addAction(cmdManager->getAction(MI_LevelSettings)); + // open fx settings instead of level settings when clicked on zerary fx + // level + if (cell.m_level && cell.m_level->getZeraryFxLevel()) + menu.addAction(cmdManager->getAction(MI_FxParamEditor)); + else + menu.addAction(cmdManager->getAction(MI_LevelSettings)); menu.addSeparator(); if (!soundCellsSelected) { @@ -3237,6 +3266,7 @@ void CellArea::createCellMenu(QMenu &menu, bool isCellSelected, TXshCell cell) { menu.addAction(cmdManager->getAction(MI_Clear)); menu.addAction(cmdManager->getAction(MI_Insert)); + menu.addAction(cmdManager->getAction(MI_Duplicate)); menu.addSeparator(); TXshSimpleLevel *sl = TApp::instance()->getCurrentLevel()->getSimpleLevel(); @@ -3360,6 +3390,7 @@ void CellArea::createKeyLineMenu(QMenu &menu, int row, int col) { menu.addAction(cmdManager->getAction(MI_SetAcceleration)); menu.addAction(cmdManager->getAction(MI_SetDeceleration)); menu.addAction(cmdManager->getAction(MI_SetConstantSpeed)); + menu.addSeparator(); } else { // Se le due chiavi non sono linear aggiungo il comando ResetInterpolation bool isR0FullK = pegbar->isFullKeyframe(r0); @@ -3369,9 +3400,32 @@ void CellArea::createKeyLineMenu(QMenu &menu, int row, int col) { TDoubleKeyframe::Type r1Type = pegbar->getParam(TStageObject::T_X)->getKeyframeAt(r1).m_prevType; if (isGlobalKeyFrameWithSameTypeDiffFromLinear(pegbar, r0) && - isGlobalKeyFrameWithSamePrevTypeDiffFromLinear(pegbar, r1)) + isGlobalKeyFrameWithSamePrevTypeDiffFromLinear(pegbar, r1)) { menu.addAction(cmdManager->getAction(MI_ResetInterpolation)); + menu.addSeparator(); + } } + + TDoubleKeyframe::Type rType = + pegbar->getParam(TStageObject::T_X)->getKeyframeAt(r0).m_type; + + if (rType != TDoubleKeyframe::Linear) + menu.addAction(cmdManager->getAction(MI_UseLinearInterpolation)); + if (rType != TDoubleKeyframe::SpeedInOut) + menu.addAction(cmdManager->getAction(MI_UseSpeedInOutInterpolation)); + if (rType != TDoubleKeyframe::EaseInOut) + menu.addAction(cmdManager->getAction(MI_UseEaseInOutInterpolation)); + if (rType != TDoubleKeyframe::EaseInOutPercentage) + menu.addAction(cmdManager->getAction(MI_UseEaseInOutPctInterpolation)); + if (rType != TDoubleKeyframe::Exponential) + menu.addAction(cmdManager->getAction(MI_UseExponentialInterpolation)); + if (rType != TDoubleKeyframe::Expression) + menu.addAction(cmdManager->getAction(MI_UseExpressionInterpolation)); + if (rType != TDoubleKeyframe::File) + menu.addAction(cmdManager->getAction(MI_UseFileInterpolation)); + if (rType != TDoubleKeyframe::Constant) + menu.addAction(cmdManager->getAction(MI_UseConstantInterpolation)); + #ifdef LINETEST menu.addSeparator(); int paramStep = getParamStep(pegbar, r0); diff --git a/toonz/sources/toonz/xshcellviewer.h b/toonz/sources/toonz/xshcellviewer.h index a552fa6..43a219a 100644 --- a/toonz/sources/toonz/xshcellviewer.h +++ b/toonz/sources/toonz/xshcellviewer.h @@ -109,6 +109,8 @@ class CellArea final : public QWidget { // Restistusce true bool getEaseHandles(int r0, int r1, double e0, double e1, int &rh0, int &rh1); + bool isKeyFrameArea(int col, int row, QPoint mouseInCell); + DragTool *getDragTool() const; void setDragTool(DragTool *dragTool); diff --git a/toonz/sources/toonz/xshcolumnviewer.cpp b/toonz/sources/toonz/xshcolumnviewer.cpp index 6894f3b..b974f4b 100644 --- a/toonz/sources/toonz/xshcolumnviewer.cpp +++ b/toonz/sources/toonz/xshcolumnviewer.cpp @@ -7,7 +7,6 @@ #include "menubarcommandids.h" #include "columnselection.h" #include "xsheetdragtool.h" -#include "tapp.h" // TnzTools includes #include "tools/toolhandle.h" @@ -788,8 +787,9 @@ void ColumnArea::DrawHeader::drawConfig() const { p.fillRect(configRect, bgColor); if (o->flag(PredefinedFlag::CONFIG_AREA_BORDER)) p.drawRect(configRect); - if (column->getSoundColumn() || column->getPaletteColumn() || - column->getSoundTextColumn()) + TXshZeraryFxColumn *zColumn = dynamic_cast(column); + + if (zColumn || column->getPaletteColumn() || column->getSoundTextColumn()) return; p.drawImage(configImgRect, icon); @@ -865,13 +865,6 @@ void ColumnArea::DrawHeader::drawColumnName() const { leftadj = 24; } - if (!o->isVerticalTimeline()) { - if (column->getSoundColumn()) - rightadj -= 97; - else if (column->getFilterColorId()) - rightadj -= 15; - } - p.setPen((isCurrent) ? m_viewer->getSelectedColumnTextColor() : nameBacklit ? Qt::black : m_viewer->getTextColor()); } else @@ -897,13 +890,14 @@ void ColumnArea::DrawHeader::drawThumbnail(QPixmap &iconPixmap) const { xsh->getColumn(col) ? xsh->getColumn(col)->getSoundColumn() : 0; drawSoundIcon(sc->isPlaying()); - drawVolumeControl(sc->getVolume()); + // Volume control now in config button. If no config button + // draw control + if (!o->flag(PredefinedFlag::CONFIG_AREA_VISIBLE)) + drawVolumeControl(sc->getVolume()); return; } - if (!o->isVerticalTimeline() || - !o->flag(PredefinedFlag::THUMBNAIL_AREA_VISIBLE)) - return; + if (!o->flag(PredefinedFlag::THUMBNAIL_AREA_VISIBLE)) return; QRect thumbnailImageRect = o->rect(PredefinedRect::THUMBNAIL).translated(orig); @@ -1112,7 +1106,8 @@ ColumnArea::ColumnArea(XsheetViewer *parent, Qt::WFlags flags) , m_col(-1) , m_columnTransparencyPopup(0) , m_transparencyPopupTimer(0) - , m_isPanning(false) { + , m_isPanning(false) + , m_soundColumnPopup(0) { TXsheetHandle *xsheetHandle = TApp::instance()->getCurrentXsheet(); #ifndef LINETEST TObjectHandle *objectHandle = TApp::instance()->getCurrentObject(); @@ -1359,7 +1354,7 @@ void ColumnArea::drawSoundColumnHead(QPainter &p, int col) { // AREA drawHeader.levelColors(columnColor, dragColor); drawHeader.drawBaseFill(columnColor, dragColor); drawHeader.drawEye(); - drawHeader.drawPreviewToggle(255); + drawHeader.drawPreviewToggle(sc ? (troundp(255.0 * sc->getVolume())) : 0); drawHeader.drawLock(); drawHeader.drawConfig(); drawHeader.drawColumnName(); @@ -1584,7 +1579,7 @@ using namespace DVGui; ColumnTransparencyPopup::ColumnTransparencyPopup(QWidget *parent) : QWidget(parent, Qt::Popup) { - setFixedWidth(8 + 30 + 8 + 100 + 8 + 8 + 8 + 7); + setFixedWidth(8 + 78 + 8 + 100 + 8 + 8 + 8 + 7); m_slider = new QSlider(Qt::Horizontal, this); m_slider->setMinimum(1); @@ -1610,6 +1605,7 @@ m_value->setFont(font);*/ } QLabel *filterLabel = new QLabel(tr("Filter:"), this); + QLabel *sliderLabel = new QLabel(tr("Opacity:"), this); QVBoxLayout *mainLayout = new QVBoxLayout(); mainLayout->setMargin(3); @@ -1619,6 +1615,7 @@ m_value->setFont(font);*/ // hlayout->setContentsMargins(0, 3, 0, 3); hlayout->setMargin(0); hlayout->setSpacing(3); + hlayout->addWidget(sliderLabel, 0); hlayout->addWidget(m_slider); hlayout->addWidget(m_value); hlayout->addWidget(new QLabel("%")); @@ -1722,6 +1719,106 @@ void ColumnTransparencyPopup::mouseReleaseEvent(QMouseEvent *e) { //------------------------------------------------------------------------------ +SoundColumnPopup::SoundColumnPopup(QWidget *parent) + : QWidget(parent, Qt::Popup) { + setFixedWidth(8 + 78 + 8 + 100 + 8 + 8 + 8 + 7); + + m_slider = new QSlider(Qt::Horizontal, this); + m_slider->setMinimum(0); + m_slider->setMaximum(100); + m_slider->setFixedHeight(14); + m_slider->setFixedWidth(100); + + m_value = new DVGui::IntLineEdit(this, 1, 1, 100); + + QLabel *sliderLabel = new QLabel(tr("Volume:"), this); + + QVBoxLayout *mainLayout = new QVBoxLayout(); + mainLayout->setMargin(3); + mainLayout->setSpacing(3); + { + QHBoxLayout *hlayout = new QHBoxLayout; + // hlayout->setContentsMargins(0, 3, 0, 3); + hlayout->setMargin(0); + hlayout->setSpacing(3); + hlayout->addWidget(sliderLabel, 0); + hlayout->addWidget(m_slider); + hlayout->addWidget(m_value); + hlayout->addWidget(new QLabel("%")); + mainLayout->addLayout(hlayout, 0); + } + setLayout(mainLayout); + + bool ret = connect(m_slider, SIGNAL(sliderReleased()), this, + SLOT(onSliderReleased())); + ret = ret && connect(m_slider, SIGNAL(sliderMoved(int)), this, + SLOT(onSliderChange(int))); + ret = ret && connect(m_slider, SIGNAL(valueChanged(int)), this, + SLOT(onSliderValueChanged(int))); + ret = ret && connect(m_value, SIGNAL(textChanged(const QString &)), this, + SLOT(onValueChanged(const QString &))); + assert(ret); +} + +//---------------------------------------------------------------- + +void SoundColumnPopup::onSliderValueChanged(int val) { + if (m_slider->isSliderDown()) return; + m_value->setText(QString::number(val)); + onSliderReleased(); +} + +void SoundColumnPopup::onSliderReleased() { + int val = m_slider->value(); + m_column->getSoundColumn()->setVolume(((double)val / 100.0)); + TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged(); + TApp::instance()->getCurrentScene()->notifySceneChanged(); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + ((ColumnArea *)parent())->update(); +} + +//----------------------------------------------------------------------- + +void SoundColumnPopup::onSliderChange(int val) { + disconnect(m_value, SIGNAL(textChanged(const QString &)), 0, 0); + m_value->setText(QString::number(val)); + connect(m_value, SIGNAL(textChanged(const QString &)), this, + SLOT(onValueChanged(const QString &))); +} + +//---------------------------------------------------------------- + +void SoundColumnPopup::onValueChanged(const QString &str) { + int val = str.toInt(); + m_slider->setValue(val); + m_column->getSoundColumn()->setVolume(((double)val / 100.0)); + + TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged(); + TApp::instance()->getCurrentScene()->notifySceneChanged(); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + ((ColumnArea *)parent())->update(); +} + +//---------------------------------------------------------------- + +void SoundColumnPopup::setColumn(TXshColumn *column) { + m_column = column; + assert(m_column); + double volume = m_column->getSoundColumn()->getVolume(); + int val = (int)troundp(100.0 * volume); + m_slider->setValue(val); + disconnect(m_value, SIGNAL(textChanged(const QString &)), 0, 0); + m_value->setText(QString::number(val)); + connect(m_value, SIGNAL(textChanged(const QString &)), this, + SLOT(onValueChanged(const QString &))); +} + +void SoundColumnPopup::mouseReleaseEvent(QMouseEvent *e) { + // hide(); +} + +//---------------------------------------------------------------- + void ColumnArea::openTransparencyPopup() { if (m_transparencyPopupTimer) m_transparencyPopupTimer->stop(); if (m_col < 0) return; @@ -1739,6 +1836,23 @@ void ColumnArea::openTransparencyPopup() { m_columnTransparencyPopup->show(); } +void ColumnArea::openSoundColumnPopup() { + if (m_col < 0) return; + TXshColumn *column = m_viewer->getXsheet()->getColumn(m_col); + if (!column || column->isEmpty()) return; + + if (!column->isCamstandVisible()) { + column->setCamstandVisible(true); + TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged(); + TApp::instance()->getCurrentScene()->notifySceneChanged(); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + update(); + } + + m_soundColumnPopup->setColumn(column); + m_soundColumnPopup->show(); +} + //---------------------------------------------------------------- void ColumnArea::startTransparencyPopupTimer(QMouseEvent *e) { // AREA @@ -1856,7 +1970,7 @@ void ColumnArea::mousePressEvent(QMouseEvent *event) { TXshZeraryFxColumn *zColumn = dynamic_cast(column); - if (zColumn || column->getSoundColumn() || column->getPaletteColumn() || + if (zColumn || column->getPaletteColumn() || column->getSoundTextColumn()) { // do nothing } else @@ -1884,7 +1998,8 @@ void ColumnArea::mousePressEvent(QMouseEvent *event) { QTimer::singleShot(interval, this, SLOT(update())); } update(); - } else if (o->rect(PredefinedRect::VOLUME_AREA).contains(mouseInCell)) + } else if (!o->flag(PredefinedFlag::CONFIG_AREA_VISIBLE) && + o->rect(PredefinedRect::VOLUME_AREA).contains(mouseInCell)) setDragTool(XsheetGUI::DragTool::makeVolumeDragTool(m_viewer)); else setDragTool(XsheetGUI::DragTool::makeColumnSelectionTool(m_viewer)); @@ -1999,7 +2114,8 @@ void ColumnArea::mouseMoveEvent(QMouseEvent *event) { // sound column if (o->rect(PredefinedRect::SOUND_ICON).contains(mouseInCell)) m_tooltip = tr("Click to play the soundtrack back"); - else if (o->rect(PredefinedRect::VOLUME_AREA).contains(mouseInCell)) + else if (!o->flag(PredefinedFlag::CONFIG_AREA_VISIBLE) && + o->rect(PredefinedRect::VOLUME_AREA).contains(mouseInCell)) m_tooltip = tr("Set the volume of the soundtrack"); } else m_tooltip = tr("Click to select column, double-click to edit"); @@ -2017,7 +2133,8 @@ void ColumnArea::mouseMoveEvent(QMouseEvent *event) { // sound column if (o->rect(PredefinedRect::SOUND_ICON).contains(mouseInCell)) m_tooltip = tr("Click to play the soundtrack back"); - else if (o->rect(PredefinedRect::VOLUME_AREA).contains(mouseInCell)) + else if (!o->flag(PredefinedFlag::CONFIG_AREA_VISIBLE) && + o->rect(PredefinedRect::VOLUME_AREA).contains(mouseInCell)) m_tooltip = tr("Set the volume of the soundtrack"); } else if (Preferences::instance()->getColumnIconLoadingPolicy() == Preferences::LoadOnDemand) @@ -2057,9 +2174,6 @@ void ColumnArea::mouseReleaseEvent(QMouseEvent *event) { else if (m_doOnRelease == ToggleLock) column->lock(!column->isLocked()); else if (m_doOnRelease == OpenSettings) { - if (!m_columnTransparencyPopup) - m_columnTransparencyPopup = new ColumnTransparencyPopup(this); - // Align popup to be below to CONFIG button QRect configRect = m_viewer->orientation()->rect(PredefinedRect::CONFIG_AREA); @@ -2073,10 +2187,24 @@ void ColumnArea::mouseReleaseEvent(QMouseEvent *event) { int y = mouseInCell.y() - configRect.bottom(); // distance from bottum edge of CONFIG button - m_columnTransparencyPopup->move(event->globalPos().x() + x, - event->globalPos().y() - y); - openTransparencyPopup(); + if (column->getSoundColumn()) { + if (!m_soundColumnPopup) + m_soundColumnPopup = new SoundColumnPopup(this); + + m_soundColumnPopup->move(event->globalPos().x() + x, + event->globalPos().y() - y); + + openSoundColumnPopup(); + } else { + if (!m_columnTransparencyPopup) + m_columnTransparencyPopup = new ColumnTransparencyPopup(this); + + m_columnTransparencyPopup->move(event->globalPos().x() + x, + event->globalPos().y() - y); + + openTransparencyPopup(); + } } else if (m_doOnRelease == ToggleAllPreviewVisible) { for (col = 0; col < totcols; col++) { TXshColumn *column = xsh->getColumn(col); diff --git a/toonz/sources/toonz/xshcolumnviewer.h b/toonz/sources/toonz/xshcolumnviewer.h index 82fda4d..d006981 100644 --- a/toonz/sources/toonz/xshcolumnviewer.h +++ b/toonz/sources/toonz/xshcolumnviewer.h @@ -178,6 +178,28 @@ protected slots: void onFilterColorChanged(int id); }; +class SoundColumnPopup final : public QWidget { + Q_OBJECT + + QSlider *m_slider; + QLineEdit *m_value; + TXshColumn *m_column; + +public: + SoundColumnPopup(QWidget *parent); + void setColumn(TXshColumn *column); + +protected: + // void mouseMoveEvent ( QMouseEvent * e ); + void mouseReleaseEvent(QMouseEvent *e) override; + +protected slots: + void onSliderReleased(); + void onSliderChange(int val); + void onSliderValueChanged(int); + void onValueChanged(const QString &); +}; + //! The class in charge of the region showing layer headers class ColumnArea final : public QWidget { Q_OBJECT @@ -193,6 +215,7 @@ class ColumnArea final : public QWidget { }; ColumnTransparencyPopup *m_columnTransparencyPopup; + SoundColumnPopup *m_soundColumnPopup; QTimer *m_transparencyPopupTimer; int m_doOnRelease; XsheetViewer *m_viewer; @@ -302,6 +325,7 @@ protected: protected slots: void onSubSampling(QAction *); void openTransparencyPopup(); + void openSoundColumnPopup(); }; //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/xsheetcmd.cpp b/toonz/sources/toonz/xsheetcmd.cpp index 2a27949..1544141 100644 --- a/toonz/sources/toonz/xsheetcmd.cpp +++ b/toonz/sources/toonz/xsheetcmd.cpp @@ -33,7 +33,6 @@ #include "toonz/txshsoundtextlevel.h" #include "toonz/tstageobjecttree.h" #include "toonz/tstageobjectkeyframe.h" -#include "toonz/txshcolumn.h" #include "toonz/stageobjectutil.h" #include "toonz/toonzfolders.h" #include "toonz/txshchildlevel.h" @@ -1687,6 +1686,63 @@ public: } ResetArrowCommand; +//----------------------------------------------------------------------------- +// Unify commands for all types of interpolation +class SetInterpolation final : public MenuItemHandler { + TDoubleKeyframe::Type m_type; + +public: + SetInterpolation(CommandId cmdId, TDoubleKeyframe::Type type) + : MenuItemHandler(cmdId), m_type(type) {} + + void execute() override { + TApp *app = TApp::instance(); + TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); + int row = app->getCurrentFrame()->getFrame(); + + TStageObjectId objectId = app->getCurrentObject()->getObjectId(); + TStageObject *pegbar = xsh->getStageObject(objectId); + if (!pegbar) return; + + int r0, r1; + double ease0, ease1; + + pegbar->getKeyframeSpan(row, r0, ease0, r1, ease1); + + KeyFrameHandleCommandUndo *undo = + new KeyFrameHandleCommandUndo(objectId, r0, r1); + + TStageObject::Keyframe k0 = pegbar->getKeyframe(r0); + TStageObject::Keyframe k1 = pegbar->getKeyframe(r1); + + for (int i = 0; i < TStageObject::T_ChannelCount; i++) { + k0.m_channels[i].m_type = m_type; + k1.m_channels[i].m_prevType = m_type; + } + pegbar->setKeyframeWithoutUndo(r0, k0); + pegbar->setKeyframeWithoutUndo(r1, k1); + + TUndoManager::manager()->add(undo); + + TApp::instance()->getCurrentScene()->setDirtyFlag(true); + TApp::instance()->getCurrentObject()->notifyObjectIdChanged(false); + } + +} UseLinearInterpolation(MI_UseLinearInterpolation, TDoubleKeyframe::Linear), + UseSpeedInOutInterpolation(MI_UseSpeedInOutInterpolation, + TDoubleKeyframe::SpeedInOut), + UseEaseInOutInterpolation(MI_UseEaseInOutInterpolation, + TDoubleKeyframe::EaseInOut), + UseEaseInOutPctInterpolation(MI_UseEaseInOutPctInterpolation, + TDoubleKeyframe::EaseInOutPercentage), + UseExponentialInterpolation(MI_UseExponentialInterpolation, + TDoubleKeyframe::Exponential), + UseExpressionInterpolation(MI_UseExpressionInterpolation, + TDoubleKeyframe::Expression), + UseFileInterpolation(MI_UseFileInterpolation, TDoubleKeyframe::File), + UseConstantInterpolation(MI_UseConstantInterpolation, + TDoubleKeyframe::Constant); + //=========================================================== // To Be Reworked //=========================================================== diff --git a/toonz/sources/toonz/xsheetdragtool.cpp b/toonz/sources/toonz/xsheetdragtool.cpp index 6909626..f8e3ce6 100644 --- a/toonz/sources/toonz/xsheetdragtool.cpp +++ b/toonz/sources/toonz/xsheetdragtool.cpp @@ -1493,7 +1493,7 @@ public: TColumnSelection *selection = getViewer()->getColumnSelection(); selection->selectNone(); int i, ia = m_firstColumn, ib = col; - if (ia > ib) tswap(ia, ib); + if (ia > ib) std::swap(ia, ib); for (i = ia; i <= ib; i++) selection->selectColumn(i, true); getViewer()->update(); refreshCellsArea(); diff --git a/toonz/sources/toonz/xsheetviewer.cpp b/toonz/sources/toonz/xsheetviewer.cpp index c1340f7..37f8fbd 100644 --- a/toonz/sources/toonz/xsheetviewer.cpp +++ b/toonz/sources/toonz/xsheetviewer.cpp @@ -32,7 +32,6 @@ #include "toonz/txshnoteset.h" #include "toonz/childstack.h" #include "toonz/txshlevelhandle.h" -#include "toonz/preferences.h" #include "tconvert.h" #include "tenv.h" diff --git a/toonz/sources/toonz/xsheetviewer.h b/toonz/sources/toonz/xsheetviewer.h index 04bf863..aa2a8fa 100644 --- a/toonz/sources/toonz/xsheetviewer.h +++ b/toonz/sources/toonz/xsheetviewer.h @@ -212,6 +212,7 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings { QColor m_verticalLineHeadColor; // vertical lines in column head QColor m_textColor; // text color (black) QColor m_previewFrameTextColor; // frame number in preview range (blue) + QColor m_onionSkinAreaBgColor; Q_PROPERTY(QColor CurrentRowBgColor READ getCurrentRowBgColor WRITE setCurrentRowBgColor) Q_PROPERTY( @@ -223,6 +224,8 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings { Q_PROPERTY(QColor TextColor READ getTextColor WRITE setTextColor) Q_PROPERTY(QColor PreviewFrameTextColor READ getPreviewFrameTextColor WRITE setPreviewFrameTextColor) + Q_PROPERTY(QColor OnionSkinAreaBgColor READ getOnionSkinAreaBgColor WRITE + setOnionSkinAreaBgColor) // Column QColor m_emptyColumnHeadColor; // empty column header (200,200,200) QColor m_selectedColumnTextColor; // selected column text (red) @@ -719,6 +722,11 @@ public: m_previewFrameTextColor = color; } QColor getPreviewFrameTextColor() const { return m_previewFrameTextColor; } + void setOnionSkinAreaBgColor(const QColor &color) { + m_onionSkinAreaBgColor = color; + } + QColor getOnionSkinAreaBgColor() const { return m_onionSkinAreaBgColor; } + // Column void setEmptyColumnHeadColor(const QColor &color) { m_emptyColumnHeadColor = color; diff --git a/toonz/sources/toonz/xshrowviewer.cpp b/toonz/sources/toonz/xshrowviewer.cpp index 99145d2..30c1541 100644 --- a/toonz/sources/toonz/xshrowviewer.cpp +++ b/toonz/sources/toonz/xshrowviewer.cpp @@ -357,6 +357,25 @@ void RowArea::drawCurrentRowGadget(QPainter &p, int r0, int r1) { //----------------------------------------------------------------------------- +void RowArea::drawOnionSkinBackground(QPainter &p, int r0, int r1) { + const Orientation *o = m_viewer->orientation(); + + int frameAdj = m_viewer->getFrameZoomAdjustment(); + + for (int r = r0; r <= r1; r++) { + QPoint basePoint = m_viewer->positionToXY(CellPosition(r, 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) basePoint.setY(0); + + QRect oRect = m_viewer->orientation() + ->rect(PredefinedRect::ONION_AREA) + .adjusted(0, 0, -frameAdj, 0) + .translated(basePoint); + p.fillRect(oRect, m_viewer->getOnionSkinAreaBgColor()); + } +} + +//----------------------------------------------------------------------------- + void RowArea::drawOnionSkinSelection(QPainter &p) { TApp *app = TApp::instance(); OnionSkinMask osMask = app->getCurrentOnionSkin()->getOnionSkinMask(); @@ -561,6 +580,105 @@ void RowArea::drawCurrentTimeLine(QPainter &p) { //----------------------------------------------------------------------------- +void RowArea::drawShiftTraceMarker(QPainter &p) { + TApp *app = TApp::instance(); + OnionSkinMask osMask = app->getCurrentOnionSkin()->getOnionSkinMask(); + + TXsheet *xsh = app->getCurrentScene()->getScene()->getXsheet(); + assert(xsh); + int currentRow = m_viewer->getCurrentRow(); + + int frameAdj = m_viewer->getFrameZoomAdjustment(); + + // get onion colors + TPixel frontPixel, backPixel; + bool inksOnly; + Preferences::instance()->getOnionData(frontPixel, backPixel, inksOnly); + QColor frontColor((int)frontPixel.r, (int)frontPixel.g, (int)frontPixel.b); + QColor backColor((int)backPixel.r, (int)backPixel.g, (int)backPixel.b); + + // draw lines to ghost frames + int prevOffset = osMask.getShiftTraceGhostFrameOffset(0); + int forwardOffset = osMask.getShiftTraceGhostFrameOffset(1); + + QRect onionRect = + m_viewer->orientation()->rect(PredefinedRect::SHIFTTRACE_DOT); + int onionCenter_frame = + m_viewer->orientation()->frameSide(onionRect).middle(); + int onionCenter_layer = + m_viewer->orientation()->layerSide(onionRect).middle(); + + if (currentRow > 0 && prevOffset < 0) // previous ghost + { + int layerAxis = onionCenter_layer; + int fromFrameAxis = m_viewer->rowToFrameAxis(currentRow + prevOffset) + + onionCenter_frame - (frameAdj / 2); + int toFrameAxis = m_viewer->rowToFrameAxis(currentRow) + onionCenter_frame - + (frameAdj / 2); + QLine verticalLine = m_viewer->orientation()->verticalLine( + layerAxis, NumberRange(fromFrameAxis, toFrameAxis)); + p.setPen(backColor); + p.setBrush(Qt::NoBrush); + p.drawLine(verticalLine); + } + if (forwardOffset > 0) // forward ghost + { + int layerAxis = onionCenter_layer; + int fromFrameAxis = m_viewer->rowToFrameAxis(currentRow) + + onionCenter_frame - (frameAdj / 2); + int toFrameAxis = m_viewer->rowToFrameAxis(currentRow + forwardOffset) + + onionCenter_frame - (frameAdj / 2); + QLine verticalLine = m_viewer->orientation()->verticalLine( + layerAxis, NumberRange(fromFrameAxis, toFrameAxis)); + p.setPen(frontColor); + p.setBrush(Qt::NoBrush); + p.drawLine(verticalLine); + } + + if (!m_viewer->orientation()->isVerticalTimeline()) + drawCurrentTimeIndicator(p); + + // draw dots + std::vector offsVec = {prevOffset, 0, forwardOffset}; + std::vector colorsVec = {backColor, QColor(0, 162, 232), frontColor}; + QFont currentFont = p.font(); + QFont tmpFont = p.font(); + tmpFont.setPointSize(7); + p.setFont(tmpFont); + for (int i = 0; i < 3; i++) { + if (i != 1 && offsVec[i] == 0) continue; + p.setPen(colorsVec[i]); + p.setBrush(Qt::gray); + QPoint topLeft = + m_viewer->positionToXY(CellPosition(currentRow + offsVec[i], 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); + QRect dotRect = m_viewer->orientation() + ->rect(PredefinedRect::SHIFTTRACE_DOT) + .translated(topLeft); + dotRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); + p.drawRect(dotRect); + // draw shortcut numbers + p.setPen(Qt::black); + p.drawText(dotRect, Qt::AlignCenter, QString::number(i + 1)); + } + p.setFont(currentFont); + + //-- onion placement hint under mouse + if (m_showOnionToSet == ShiftTraceGhost) { + p.setPen(QColor(255, 255, 0)); + p.setBrush(QColor(255, 255, 0, 180)); + QPoint topLeft = m_viewer->positionToXY(CellPosition(m_row, 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); + QRect dotRect = m_viewer->orientation() + ->rect(PredefinedRect::SHIFTTRACE_DOT) + .translated(topLeft); + dotRect.adjust(-frameAdj / 2, 0, -frameAdj / 2, 0); + p.drawRect(dotRect); + } +} + +//----------------------------------------------------------------------------- + namespace { TStageObjectId getAncestor(TXsheet *xsh, TStageObjectId id) { @@ -660,6 +778,9 @@ void RowArea::paintEvent(QPaintEvent *event) { drawPlayRangeBackground(p, r0, r1); + if (Preferences::instance()->isOnionSkinEnabled()) + drawOnionSkinBackground(p, r0, r1); + if (TApp::instance()->getCurrentFrame()->isEditingScene()) // current frame drawCurrentRowGadget(p, r0, r1); @@ -672,7 +793,9 @@ void RowArea::paintEvent(QPaintEvent *event) { drawRows(p, r0, r1); if (TApp::instance()->getCurrentFrame()->isEditingScene()) { - if (Preferences::instance()->isOnionSkinEnabled()) + if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked()) + drawShiftTraceMarker(p); + else if (Preferences::instance()->isOnionSkinEnabled()) drawOnionSkinSelection(p); else if (Preferences::instance()->isCurrentTimelineIndicatorEnabled() && !m_viewer->orientation()->isVerticalTimeline()) @@ -711,10 +834,41 @@ void RowArea::mousePressEvent(QMouseEvent *event) { QPoint mouseInCell = event->pos() - topLeft; int frameAdj = m_viewer->getFrameZoomAdjustment(); - if (Preferences::instance()->isOnionSkinEnabled() && - o->rect(PredefinedRect::ONION_AREA) + if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked() && + o->rect(PredefinedRect::SHIFTTRACE_DOT_AREA) .adjusted(0, 0, -frameAdj, 0) .contains(mouseInCell)) { + // Reset ghosts to neighbor frames + if (row == currentFrame) + OnioniSkinMaskGUI::resetShiftTraceFrameOffset(); + else { + OnionSkinMask osMask = + TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask(); + int prevOffset = osMask.getShiftTraceGhostFrameOffset(0); + int forwardOffset = osMask.getShiftTraceGhostFrameOffset(1); + // Hide previous ghost + if (row == currentFrame + prevOffset) + osMask.setShiftTraceGhostFrameOffset(0, 0); + // Hide forward ghost + else if (row == currentFrame + forwardOffset) + osMask.setShiftTraceGhostFrameOffset(1, 0); + // Move previous ghost + else if (row < currentFrame) + osMask.setShiftTraceGhostFrameOffset(0, row - currentFrame); + // Move forward ghost + else + osMask.setShiftTraceGhostFrameOffset(1, row - currentFrame); + TApp::instance()->getCurrentOnionSkin()->setOnionSkinMask(osMask); + } + TApp::instance()->getCurrentOnionSkin()->notifyOnionSkinMaskChanged(); + return; + } else if (!CommandManager::instance() + ->getAction(MI_ShiftTrace) + ->isChecked() && + Preferences::instance()->isOnionSkinEnabled() && + o->rect(PredefinedRect::ONION_AREA) + .adjusted(0, 0, -frameAdj, 0) + .contains(mouseInCell)) { if (row == currentFrame) { setDragTool( XsheetGUI::DragTool::makeCurrentFrameModifierTool(m_viewer)); @@ -729,11 +883,6 @@ void RowArea::mousePressEvent(QMouseEvent *event) { .contains(mouseInCell)) setDragTool(XsheetGUI::DragTool::makeKeyOnionSkinMaskModifierTool( m_viewer, false)); - else { - setDragTool( - XsheetGUI::DragTool::makeCurrentFrameModifierTool(m_viewer)); - frameAreaIsClicked = true; - } } else { int playR0, playR1, step; XsheetGUI::getPlayRange(playR0, playR1, step); @@ -833,8 +982,38 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); QPoint mouseInCell = event->pos() - topLeft; if (row < 0) return; + + m_tooltip = tr(""); + + // whether to show ability to move the shift and trace ghost frame + if (CommandManager::instance()->getAction(MI_ShiftTrace)->isChecked()) { + if (o->rect(PredefinedRect::SHIFTTRACE_DOT_AREA) + .adjusted(0, 0, -frameAdj, 0) + .contains(mouseInCell)) { + m_showOnionToSet = ShiftTraceGhost; + + OnionSkinMask osMask = + TApp::instance()->getCurrentOnionSkin()->getOnionSkinMask(); + int prevOffset = osMask.getShiftTraceGhostFrameOffset(0); + int forwardOffset = osMask.getShiftTraceGhostFrameOffset(1); + if (row == currentRow) + m_tooltip = + tr("Click to Reset Shift & Trace Markers to Neighbor Frames\nHold " + "F2 Key on the Viewer to Show This Frame Only"); + else if (row == currentRow + prevOffset) + m_tooltip = + tr("Click to Hide This Frame from Shift & Trace\nHold F1 Key on " + "the Viewer to Show This Frame Only"); + else if (row == currentRow + forwardOffset) + m_tooltip = + tr("Click to Hide This Frame from Shift & Trace\nHold F3 Key on " + "the Viewer to Show This Frame Only"); + else + m_tooltip = tr("Click to Move Shift & Trace Marker"); + } + } // whether to show ability to set onion marks - if (Preferences::instance()->isOnionSkinEnabled() && row != currentRow) { + else if (Preferences::instance()->isOnionSkinEnabled() && row != currentRow) { if (o->rect(PredefinedRect::ONION_FIXED_DOT_AREA) .adjusted(0, 0, -frameAdj, 0) .contains(mouseInCell)) @@ -884,6 +1063,7 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { QPainterPath endArrow = o->path(PredefinedPath::END_PLAY_RANGE).translated(base1); + if (!m_tooltip.isEmpty()) return; if (startArrow.contains(m_pos)) m_tooltip = tr("Playback Start Marker"); else if (endArrow.contains(m_pos)) @@ -904,8 +1084,6 @@ void RowArea::mouseMoveEvent(QMouseEvent *event) { m_tooltip = tr("Fixed Onion Skin Toggle"); else if (m_showOnionToSet == Mos) m_tooltip = tr("Relative Onion Skin Toggle"); - else - m_tooltip = tr(""); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/xshrowviewer.h b/toonz/sources/toonz/xshrowviewer.h index d7af6f7..cb8e8e8 100644 --- a/toonz/sources/toonz/xshrowviewer.h +++ b/toonz/sources/toonz/xshrowviewer.h @@ -26,8 +26,9 @@ class RowArea final : public QWidget { enum ShowOnionToSetFlag { None = 0, Fos, - Mos - } m_showOnionToSet; // TODO:�����͂����Fos,Mos�ǂ�����n�C���C�g���Ă���̂����肳����I�I�I�I + Mos, + ShiftTraceGhost + } m_showOnionToSet; enum Direction { up = 0, down }; @@ -47,10 +48,12 @@ class RowArea final : public QWidget { void drawPlayRangeBackground(QPainter &p, int r0, int r1); void drawPlayRange(QPainter &p, int r0, int r1); void drawCurrentRowGadget(QPainter &p, int r0, int r1); + void drawOnionSkinBackground(QPainter &p, int r0, int r1); void drawOnionSkinSelection(QPainter &p); void drawPinnedCenterKeys(QPainter &p, int r0, int r1); void drawCurrentTimeIndicator(QPainter &p); void drawCurrentTimeLine(QPainter &p); + void drawShiftTraceMarker(QPainter &p); DragTool *getDragTool() const; void setDragTool(DragTool *dragTool); diff --git a/toonz/sources/toonzfarm/tfarmserver/tfarmserver.cpp b/toonz/sources/toonzfarm/tfarmserver/tfarmserver.cpp index c73fd02..b9281ec 100644 --- a/toonz/sources/toonzfarm/tfarmserver/tfarmserver.cpp +++ b/toonz/sources/toonzfarm/tfarmserver/tfarmserver.cpp @@ -264,7 +264,7 @@ public: } FarmControllerProxyP &operator=(const FarmControllerProxyP &src) { FarmControllerProxyP tmp(*this); - tswap(tmp.m_proxy, m_proxy); + std::swap(tmp.m_proxy, m_proxy); return *this; } diff --git a/toonz/sources/toonzlib/CMakeLists.txt b/toonz/sources/toonzlib/CMakeLists.txt index bc03c7c..7648d6c 100644 --- a/toonz/sources/toonzlib/CMakeLists.txt +++ b/toonz/sources/toonzlib/CMakeLists.txt @@ -156,6 +156,7 @@ set(MOC_HEADERS texturemanager.h imagebuilders.h ../include/orientation.h + ../include/toonz/boardsettings.h ) set(HEADERS ${MOC_HEADERS}) @@ -317,6 +318,7 @@ set(SOURCES plasticdeformerfx.cpp txshmeshcolumn.cpp textureutils.cpp + boardsettings.cpp ) if(BUILD_TARGET_WIN) diff --git a/toonz/sources/toonzlib/autoadjust.cpp b/toonz/sources/toonzlib/autoadjust.cpp index 0c65622..b15d077 100644 --- a/toonz/sources/toonzlib/autoadjust.cpp +++ b/toonz/sources/toonzlib/autoadjust.cpp @@ -74,8 +74,8 @@ void set_autoadjust_window(int x0, int y0, int x1, int y1) { Window_y0 = y0; Window_x1 = x1; Window_y1 = y1; - if (Window_x0 > Window_x1) tswap(Window_x0, Window_x1); - if (Window_y0 > Window_y1) tswap(Window_y0, Window_y1); + if (Window_x0 > Window_x1) std::swap(Window_x0, Window_x1); + if (Window_y0 > Window_y1) std::swap(Window_y0, Window_y1); } /*---------------------------------------------------------------------------*/ diff --git a/toonz/sources/toonzlib/autoclose.cpp b/toonz/sources/toonzlib/autoclose.cpp index 36bfadf..48220e7 100644 --- a/toonz/sources/toonzlib/autoclose.cpp +++ b/toonz/sources/toonzlib/autoclose.cpp @@ -217,8 +217,8 @@ return; int y2 = s.second.y; if (x1 > x2) { - tswap(x1, x2); - tswap(y1, y2); + std::swap(x1, x2); + std::swap(y1, y2); } buf += y1 * wrap + x1; diff --git a/toonz/sources/toonzlib/autopos.cpp b/toonz/sources/toonzlib/autopos.cpp index b596d64..e00300f 100644 --- a/toonz/sources/toonzlib/autopos.cpp +++ b/toonz/sources/toonzlib/autopos.cpp @@ -17,14 +17,9 @@ fare resize e realloc size dello stack a 65000 unita' */ -#if defined(MACOSX) || defined(LINUX) -#define TRUE 1 -#define FALSE 0 -#endif - #define SECURITY_MARGIN_MM 4.0 -static int Debug_flag = FALSE; +static bool Debug_flag = false; /*===========================================================================*/ /* @@ -38,7 +33,7 @@ static int Debug_flag = FALSE; #define AUTOAL_WHITE_COLS 2 #define AUTOAL_THRESHOLD 160 -static int autoalign_gr8(UCHAR *buffer_gr8, int wrap, int lx, int ly, +static bool autoalign_gr8(UCHAR *buffer_gr8, int wrap, int lx, int ly, int pix_origin, int dpix_dx, int dpix_dy, int strip_width) { int first_x[2], dx_dcol[2], target[2]; @@ -83,7 +78,7 @@ static int autoalign_gr8(UCHAR *buffer_gr8, int wrap, int lx, int ly, } } } - return FALSE; + return false; found: @@ -127,12 +122,12 @@ found: } } } - return TRUE; + return true; } /*---------------------------------------------------------------------------*/ -static int autoalign_rgb(TPixel32 *buffer_rgb, int wrap, int lx, int ly, +static bool autoalign_rgb(TPixel32 *buffer_rgb, int wrap, int lx, int ly, int pix_origin, int dpix_dx, int dpix_dy, int strip_width) { int first_x[2], dx_dcol[2], target[2]; @@ -177,7 +172,7 @@ static int autoalign_rgb(TPixel32 *buffer_rgb, int wrap, int lx, int ly, } } } - return FALSE; + return false; found: @@ -225,12 +220,12 @@ found: } } } - return TRUE; + return true; } /*---------------------------------------------------------------------------*/ -int do_autoalign(const TRasterImageP &image) { +bool do_autoalign(const TRasterImageP &image) { int wrap, lx, ly, mx, my; int pix_origin, dpix_dx, dpix_dy; int strip_width; @@ -260,7 +255,7 @@ int do_autoalign(const TRasterImageP &image) { TRasterGR8P ras8(ras); TRaster32P ras32(ras); ras->lock(); - int ret = FALSE; + bool ret = false; if (ras8) ret = autoalign_gr8(ras8->getRawData(), wrap, lx, ly, pix_origin, dpix_dx, @@ -274,7 +269,7 @@ int do_autoalign(const TRasterImageP &image) { ras->unlock(); - return FALSE; + return false; } /*===========================================================================*/ @@ -369,7 +364,7 @@ static int Xmin, Xmax, Ymin, Ymax, Npix; #ifdef RECURSIVE_VERSION static int Level, Max_level; #endif -static int Very_black_found; +static bool Very_black_found; #ifdef DAFARE #ifdef RECURSIVE_VERSION @@ -401,7 +396,7 @@ visit_bw(int i, int j, int x, int y, int bit, UCHAR *byte), //! The found pegs are in array dots. The function checks, which of those best //! fits the reference in //! reference. The three best matching dots are returned in parameters i, j, k. -static int compare_dots(DOT const dots[], int ndots, DOT reference[], +static bool compare_dots(DOT const dots[], int ndots, DOT reference[], int ref_dot, int &i, int &j, int &k); #define REVERSE(byte, bit) \ @@ -429,7 +424,7 @@ static int Stack_size = 0; Stack_alloc_size = 65500; \ Stack_size = 0; \ Stack = (STACK_INFO *)malloc(Stack_alloc_size * sizeof(STACK_INFO)); \ - if (!Stack) return FALSE; \ + if (!Stack) return false; \ } #define DESTROY_STACK \ @@ -513,7 +508,7 @@ static int find_dots_bw(const TRasterP &img, int strip_width, UCHAR *byte, *buffer; int dot_lx, dot_ly; float dot_x, dot_y; - int vertical; + bool vertical; if (img->type == RAS_WB) Black_pixel = 1; @@ -531,7 +526,7 @@ static int find_dots_bw(const TRasterP &img, int strip_width, y0 = pegs_side == PEGS_BOTTOM ? 0 : img->ly - strip_width; xsize = img->lx; ysize = strip_width; - vertical = FALSE; + vertical = false; break; case PEGS_LEFT: @@ -540,7 +535,7 @@ static int find_dots_bw(const TRasterP &img, int strip_width, y0 = 0; xsize = strip_width; ysize = img->ly; - vertical = TRUE; + vertical = true; break; default: { @@ -548,7 +543,8 @@ static int find_dots_bw(const TRasterP &img, int strip_width, os << "find dots internal error: pegs_side = " << std::hex << pegs_side << '\0'; throw TCleanupException(os.str().c_str()); - x0 = y0 = xsize = ysize = vertical = 0; + x0 = y0 = xsize = ysize = 0; + vertical = false; } } xlast = x0 + xsize - 1; @@ -652,7 +648,7 @@ static int find_dots_gr8(const TRasterGR8P &img, int strip_width, UCHAR *pix, *buffer; int dot_lx, dot_ly; float dot_x, dot_y; - int vertical; + bool vertical; switch (pegs_side) { case PEGS_BOTTOM: @@ -661,7 +657,7 @@ static int find_dots_gr8(const TRasterGR8P &img, int strip_width, y0 = pegs_side == PEGS_BOTTOM ? 0 : img->getLy() - strip_width; xsize = img->getLx(); ysize = strip_width; - vertical = FALSE; + vertical = false; break; case PEGS_LEFT: case PEGS_RIGHT: @@ -669,14 +665,15 @@ static int find_dots_gr8(const TRasterGR8P &img, int strip_width, y0 = 0; xsize = strip_width; ysize = img->getLy(); - vertical = TRUE; + vertical = true; break; default: { std::ostringstream os; os << "find dots internal error: pegs_side = " << std::hex << pegs_side << '\0'; throw TCleanupException(os.str().c_str()); - x0 = y0 = xsize = ysize = vertical = 0; + x0 = y0 = xsize = ysize = 0; + vertical = false; } } @@ -776,7 +773,7 @@ static int find_dots_rgb(const TRaster32P &img, int strip_width, TPixel32 *pix, *buffer; int dot_lx, dot_ly; float dot_x, dot_y; - int vertical; + bool vertical; assert(img->getPixelSize() == 4); /*questo e' per ricordare che l'algo e' per RGB*/ @@ -787,7 +784,7 @@ static int find_dots_rgb(const TRaster32P &img, int strip_width, y0 = pegs_side == PEGS_BOTTOM ? 0 : img->getLy() - strip_width; xsize = img->getLx(); ysize = strip_width; - vertical = FALSE; + vertical = false; break; case PEGS_LEFT: case PEGS_RIGHT: @@ -795,14 +792,15 @@ static int find_dots_rgb(const TRaster32P &img, int strip_width, y0 = 0; xsize = strip_width; ysize = img->getLy(); - vertical = TRUE; + vertical = true; break; default: { std::ostringstream os; os << "find dots internal error: pegs_side = " << std::hex << pegs_side << '\0'; throw TCleanupException(os.str().c_str()); - x0 = y0 = xsize = ysize = vertical = 0; + x0 = y0 = xsize = ysize = 0; + vertical = false; break; } } @@ -1030,7 +1028,7 @@ start: ADDBIG(Xsum, x * weight); ADDBIG(Ysum, y * weight); ADDBIG(Weightsum, weight); - if (IS_VERY_BLACK_GR8(pix)) Very_black_found = TRUE; + if (IS_VERY_BLACK_GR8(pix)) Very_black_found = true; if (x < Xmin) Xmin = x; if (x > Xmax) Xmax = x; if (y < Ymin) Ymin = y; @@ -1103,7 +1101,7 @@ static void visit_gr8(int i, int j, int x, int y, UCHAR *pix) { ADDBIG(Xsum, x * weight); ADDBIG(Ysum, y * weight); ADDBIG(Weightsum, weight); - if (IS_VERY_BLACK_GR8(pix)) Very_black_found = TRUE; + if (IS_VERY_BLACK_GR8(pix)) Very_black_found = true; if (x < Xmin) Xmin = x; if (x > Xmax) Xmax = x; if (y < Ymin) Ymin = y; @@ -1135,7 +1133,7 @@ start: ADDBIG(Xsum, x * weight); ADDBIG(Ysum, y * weight); ADDBIG(Weightsum, weight); - if (IS_VERY_BLACK_RGB(pix)) Very_black_found = TRUE; + if (IS_VERY_BLACK_RGB(pix)) Very_black_found = true; if (x < Xmin) Xmin = x; if (x > Xmax) Xmax = x; if (y < Ymin) Ymin = y; @@ -1208,7 +1206,7 @@ static void visit_rgb(int i, int j, int x, int y, TPixel32 *pix) { ADDBIG(Xsum, x * weight); ADDBIG(Ysum, y * weight); ADDBIG(Weightsum, weight); - if (IS_VERY_BLACK_RGB(pix)) Very_black_found = TRUE; + if (IS_VERY_BLACK_RGB(pix)) Very_black_found = true; if (x < Xmin) Xmin = x; if (x > Xmax) Xmax = x; if (y < Ymin) Ymin = y; @@ -1238,12 +1236,13 @@ static void visit_rgb(int i, int j, int x, int y, TPixel32 *pix) { * questo livello. * Inoltre: la pegs_side si riferisce alle coordinate di raster. */ -int get_image_rotation_and_center(const TRasterP &img, int strip_width, +bool get_image_rotation_and_center(const TRasterP &img, int strip_width, PEGS_SIDE pegs_side, double *p_ang, double *cx, double *cy, DOT ref[], int ref_dot) { double angle; - int found, i; + int i; + bool found; float dx, dy; DOT _dotarray[MAX_DOT]; DOT *dotarray = _dotarray; @@ -1287,7 +1286,7 @@ int get_image_rotation_and_center(const TRasterP &img, int strip_width, /* controllo il pattern delle perforazioni */ if (ndot <= 1) { - return FALSE; + return false; } int indexArray[3] = {0, 1, 2}; @@ -1300,7 +1299,7 @@ int get_image_rotation_and_center(const TRasterP &img, int strip_width, stampa_dot(dotarray + i); } - if (!found) return FALSE; + if (!found) return false; angle = 0; for (i = 0; i < 2; i++) { @@ -1340,13 +1339,13 @@ int get_image_rotation_and_center(const TRasterP &img, int strip_width, printf("\nang: %g\ncx : %g\ncy : %g\n\n", *p_ang, *cx, *cy); } - return TRUE; + return true; } /*---------------------------------------------------------------------------*/ #define MIN_V 100.0 -static int compare_dots(DOT const dots[], int ndots, DOT reference[], +static bool compare_dots(DOT const dots[], int ndots, DOT reference[], int ref_dot, int &i_ok, int &j_ok, int &k_ok) { int found; int toll; @@ -1482,12 +1481,12 @@ static int compare_dots(DOT const dots[], int ndots, DOT reference[], if (ref_dis) free(ref_dis); if (dot_ok) free(dot_ok); - return TRUE; + return true; error: if (ref_dis) free(ref_dis); if (dot_ok) free(dot_ok); - return FALSE; + return false; } /*---------------------------------------------------------------------------*/ diff --git a/toonz/sources/toonzlib/autopos.h b/toonz/sources/toonzlib/autopos.h index 1f3442f..80f8bde 100644 --- a/toonz/sources/toonzlib/autopos.h +++ b/toonz/sources/toonzlib/autopos.h @@ -9,14 +9,14 @@ /*---------------------------------------------------------------------------*/ -int do_autoalign(const TRasterImageP &image); +bool do_autoalign(const TRasterImageP &image); int compute_strip_pixel(CleanupTypes::FDG_INFO *fdg, double dpi); void convert_dots_mm_to_pixel(CleanupTypes::DOT *dots, int nd, double x_res, double y_res); -int get_image_rotation_and_center(const TRasterP &img, int strip_width, +bool get_image_rotation_and_center(const TRasterP &img, int strip_width, CleanupTypes::PEGS_SIDE pegs_side, double *p_ang, double *cx, double *cy, CleanupTypes::DOT ref[], int ref_dot); diff --git a/toonz/sources/toonzlib/boardsettings.cpp b/toonz/sources/toonzlib/boardsettings.cpp new file mode 100644 index 0000000..16d4628 --- /dev/null +++ b/toonz/sources/toonzlib/boardsettings.cpp @@ -0,0 +1,364 @@ +#include "toonz/boardsettings.h" + +// TnzLib includes +#include "toonz/toonzscene.h" +#include "toonz/tproject.h" +#include "toonz/sceneproperties.h" +#include "toonz/toonzfolders.h" +#include "toutputproperties.h" +#include "tsystem.h" + +#include +#include +#include +#include +#include + +namespace { +QMap strs = { + {BoardItem::FreeText, L"FreeText"}, + {BoardItem::ProjectName, L"ProjectName"}, + {BoardItem::SceneName, L"SceneName"}, + {BoardItem::Duration_Frame, L"Duration_Frame"}, + {BoardItem::Duration_SecFrame, L"Duration_SecFrame"}, + {BoardItem::Duration_HHMMSSFF, L"Duration_HHMMSSFF"}, + {BoardItem::CurrentDate, L"CurrentDate"}, + {BoardItem::CurrentDateTime, L"CurrentDateTime"}, + {BoardItem::UserName, L"UserName"}, + {BoardItem::ScenePath_Aliased, L"ScenePath_Aliased"}, + {BoardItem::ScenePath_Full, L"ScenePath_Full"}, + {BoardItem::MoviePath_Aliased, L"MoviePath_Aliased"}, + {BoardItem::MoviePath_Full, L"MoviePath_Full"}, + {BoardItem::Image, L"Image"}}; + +std::wstring type2String(BoardItem::Type type) { return strs.value(type, L""); } +BoardItem::Type string2Type(std::wstring str) { + return strs.key(str, BoardItem::TypeCount); +} +}; + +BoardItem::BoardItem() { + m_name = "Item"; + m_type = ProjectName; + m_rect = QRectF(0.1, 0.1, 0.8, 0.8); + m_maximumFontSize = 300; + m_color = Qt::black; +} + +QString BoardItem::getContentText(ToonzScene *scene) { + switch (m_type) { + case FreeText: + return m_text; + break; + case ProjectName: + return scene->getProject()->getName().getQString(); + break; + case SceneName: + return QString::fromStdWString(scene->getSceneName()); + break; + case Duration_Frame: + return QString::number(scene->getFrameCount()); + break; + case Duration_SecFrame: { + TOutputProperties *oprop = scene->getProperties()->getOutputProperties(); + int fps = (int)oprop->getFrameRate(); + int frame = scene->getFrameCount(); + return QString("%1 + %2").arg(QString::number(frame / fps), + QString::number(frame % fps)); + } break; + case Duration_HHMMSSFF: { + TOutputProperties *oprop = scene->getProperties()->getOutputProperties(); + int fps = (int)oprop->getFrameRate(); + int frame = scene->getFrameCount(); + int hh = frame / (fps * 60 * 60); + frame -= hh * fps * 60 * 60; + int mm = frame / (fps * 60); + frame -= mm * fps * 60; + int ss = frame / fps; + int ff = frame % fps; + return QString::number(hh).rightJustified(2, '0') + ":" + + QString::number(mm).rightJustified(2, '0') + ":" + + QString::number(ss).rightJustified(2, '0') + ":" + + QString::number(ff).rightJustified(2, '0'); + } break; + case CurrentDate: + return QDate::currentDate().toString(Qt::DefaultLocaleLongDate); + break; + case CurrentDateTime: + return QDateTime::currentDateTime().toString(Qt::DefaultLocaleLongDate); + break; + case UserName: + return TSystem::getUserName(); + break; + case ScenePath_Aliased: + return scene->codeFilePath(scene->getScenePath()).getQString(); + break; + case ScenePath_Full: + return scene->decodeFilePath(scene->getScenePath()).getQString(); + break; + case MoviePath_Aliased: { + TOutputProperties *oprop = scene->getProperties()->getOutputProperties(); + return scene->codeFilePath(oprop->getPath()).getQString(); + } break; + case MoviePath_Full: { + TOutputProperties *oprop = scene->getProperties()->getOutputProperties(); + return scene->decodeFilePath(oprop->getPath()).getQString(); + } break; + } + return QString(); +} + +QRectF BoardItem::getItemRect(QSize imgSize) { + QSizeF imgSizeF(imgSize); + return QRectF( + imgSizeF.width() * m_rect.left(), imgSizeF.height() * m_rect.top(), + imgSizeF.width() * m_rect.width(), imgSizeF.height() * m_rect.height()); +} + +void BoardItem::drawItem(QPainter &p, QSize imgSize, int shrink, + ToonzScene *scene) { + QRectF itemRect = getItemRect(imgSize); + + if (m_type == Image) { + if (m_imgPath.isEmpty()) return; + TFilePath decodedPath = scene->decodeFilePath(m_imgPath); + QImage img(decodedPath.getQString()); + if (m_imgARMode == Qt::KeepAspectRatio) { + float ratio = std::min((float)itemRect.width() / (float)img.width(), + (float)itemRect.height() / (float)img.height()); + QSizeF imgSize((float)img.width() * ratio, (float)img.height() * ratio); + QPointF imgTopLeft = + itemRect.topLeft() + + QPointF((itemRect.width() - imgSize.width()) * 0.5f, + (itemRect.height() - imgSize.height()) * 0.5f); + + p.drawImage(QRectF(imgTopLeft, imgSize), img); + } else if (m_imgARMode == Qt::IgnoreAspectRatio) + p.drawImage(itemRect, img); + return; + } + + QString contentText = getContentText(scene); + + QFont tmpFont(m_font); + tmpFont.setPixelSize(100); + QFontMetricsF tmpFm(tmpFont); + QRectF tmpBounding = + tmpFm.boundingRect(itemRect, Qt::AlignLeft | Qt::AlignTop, contentText); + + float ratio = std::min(itemRect.width() / tmpBounding.width(), + itemRect.height() / tmpBounding.height()); + + // compute the font size which will just fit the item region + int fontSize = (int)(100.0f * ratio); + tmpFont.setPixelSize(fontSize); + tmpFm = QFontMetricsF(tmpFont); + tmpBounding = + tmpFm.boundingRect(itemRect, Qt::AlignLeft | Qt::AlignTop, contentText); + bool isInRect; + if (itemRect.width() >= tmpBounding.width() && + itemRect.height() >= tmpBounding.height()) + isInRect = true; + else + isInRect = false; + while (1) { + fontSize += (isInRect) ? 1 : -1; + if (fontSize <= 0) // cannot draw + return; + tmpFont.setPixelSize(fontSize); + tmpFm = QFontMetricsF(tmpFont); + tmpBounding = + tmpFm.boundingRect(itemRect, Qt::AlignLeft | Qt::AlignTop, contentText); + + bool newIsInRect = (itemRect.width() >= tmpBounding.width() && + itemRect.height() >= tmpBounding.height()); + if (isInRect != newIsInRect) { + if (isInRect) fontSize--; + break; + } + } + + //---- + fontSize = std::min(fontSize, m_maximumFontSize / shrink); + + QFont font(m_font); + font.setPixelSize(fontSize); + + p.setFont(font); + p.setPen(m_color); + + if (m_type == FreeText) + p.drawText(itemRect, Qt::AlignLeft | Qt::AlignTop, contentText); + else + p.drawText(itemRect, Qt::AlignCenter, contentText); +} + +void BoardItem::saveData(TOStream &os) { + os.child("type") << type2String(m_type); + os.child("name") << m_name; + os.child("rect") << m_rect.x() << m_rect.y() << m_rect.width() + << m_rect.height(); + + if (m_type == Image) { + // if the path is in library folder, then save the realtive path + TFilePath libFp = ToonzFolder::getLibraryFolder(); + if (libFp.isAncestorOf(m_imgPath)) + os.child("imgPath") << 1 << m_imgPath - libFp; + else + os.child("imgPath") << 0 << m_imgPath; + os.child("imgARMode") << (int)m_imgARMode; + } else { + if (m_type == FreeText) os.child("text") << m_text; + + os.child("maximumFontSize") << m_maximumFontSize; + os.child("color") << m_color.red() << m_color.green() << m_color.blue() + << m_color.alpha(); + os.child("font") << m_font.family() << (int)(m_font.bold() ? 1 : 0) + << (int)(m_font.italic() ? 1 : 0); + } +} + +void BoardItem::loadData(TIStream &is) { + std::string tagName; + while (is.matchTag(tagName)) { + if (tagName == "type") { + std::wstring typeStr; + is >> typeStr; + m_type = string2Type(typeStr); + } else if (tagName == "name") { + std::wstring str; + is >> str; + m_name = QString::fromStdWString(str); + } else if (tagName == "rect") { + double x, y, width, height; + is >> x >> y >> width >> height; + m_rect = QRectF(x, y, width, height); + } else if (tagName == "imgPath") { + int isInLibrary; + TFilePath fp; + is >> isInLibrary >> fp; + if (isInLibrary == 1) + m_imgPath = ToonzFolder::getLibraryFolder() + fp; + else + m_imgPath = fp; + } else if (tagName == "imgARMode") { + int mode; + is >> mode; + m_imgARMode = (Qt::AspectRatioMode)mode; + } else if (tagName == "text") { + std::wstring str; + is >> str; + m_text = QString::fromStdWString(str); + } else if (tagName == "maximumFontSize") { + is >> m_maximumFontSize; + } else if (tagName == "color") { + int r, g, b, a; + is >> r >> g >> b >> a; + m_color = QColor(r, g, b, a); + } else if (tagName == "font") { + QString family; + int isBold, isItalic; + is >> family >> isBold >> isItalic; + m_font.setFamily(family); + m_font.setBold(isBold == 1); + m_font.setItalic(isItalic == 1); + } else + throw TException("unexpected tag: " + tagName); + is.closeChild(); + } +} + +//====================================================================================== + +BoardSettings::BoardSettings() { + // add one item as an example + m_items.push_back(BoardItem()); +} + +QImage BoardSettings::getBoardImage(TDimension &dim, int shrink, + ToonzScene *scene) { + QImage img(dim.lx, dim.ly, QImage::Format_ARGB32); + + QPainter painter(&img); + + painter.fillRect(img.rect(), Qt::white); + + // draw each item + for (int i = m_items.size() - 1; i >= 0; i--) + m_items[i].drawItem(painter, img.rect().size(), shrink, scene); + + painter.end(); + + return img; +} + +TRaster32P BoardSettings::getBoardRaster(TDimension &dim, int shrink, + ToonzScene *scene) { + QImage img = getBoardImage(dim, shrink, scene); + + // convert QImage to TRaster + TRaster32P boardRas(dim); + int img_y = img.height() - 1; + for (int j = 0; j < dim.ly; j++, img_y--) { + TPixel32 *pix = boardRas->pixels(j); + QRgb *img_p = (QRgb *)img.scanLine(img_y); + for (int i = 0; i < dim.lx; i++, pix++, img_p++) { + (*pix).r = (typename TPixel32::Channel)(qRed(*img_p)); + (*pix).g = (typename TPixel32::Channel)(qGreen(*img_p)); + (*pix).b = (typename TPixel32::Channel)(qBlue(*img_p)); + (*pix).m = (typename TPixel32::Channel)(qAlpha(*img_p)); + } + } + return boardRas; +} + +void BoardSettings::addNewItem(int insertAt) { + m_items.insert(insertAt, BoardItem()); +} + +void BoardSettings::removeItem(int index) { + if (index < 0 || index >= m_items.size()) return; + m_items.removeAt(index); +} + +void BoardSettings::swapItems(int i, int j) { m_items.swap(i, j); } + +void BoardSettings::saveData(TOStream &os, bool forPreset) { + if (!forPreset) os.child("active") << (int)((m_active) ? 1 : 0); + os.child("duration") << m_duration; + if (!m_items.isEmpty()) { + os.openChild("boardItems"); + for (int i = 0; i < getItemCount(); i++) { + os.openChild("item"); + m_items[i].saveData(os); + os.closeChild(); + } + os.closeChild(); + } +} + +void BoardSettings::loadData(TIStream &is) { + std::string tagName; + while (is.matchTag(tagName)) { + if (tagName == "active") { + int val; + is >> val; + setActive(val == 1); + } else if (tagName == "duration") { + is >> m_duration; + } else if (tagName == "boardItems") { + m_items.clear(); + while (is.matchTag(tagName)) { + if (tagName == "item") { + BoardItem item; + item.loadData(is); + m_items.append(item); + } else + throw TException("unexpected tag: " + tagName); + is.closeChild(); + } + } else + throw TException("unexpected tag: " + tagName); + is.closeChild(); + } +} \ No newline at end of file diff --git a/toonz/sources/toonzlib/fillutil.cpp b/toonz/sources/toonzlib/fillutil.cpp index 2d5e968..497ade7 100644 --- a/toonz/sources/toonzlib/fillutil.cpp +++ b/toonz/sources/toonzlib/fillutil.cpp @@ -566,8 +566,8 @@ void InkSegmenter::drawSegment( int y2 = p1.y; if (x1 > x2) { - tswap(x1, x2); - tswap(y1, y2); + std::swap(x1, x2); + std::swap(y1, y2); } TPixelCM32 *buf = m_r->pixels() + y1 * m_wrap + x1; diff --git a/toonz/sources/toonzlib/fxcommand.cpp b/toonz/sources/toonzlib/fxcommand.cpp index 1234217..0ea8a78 100644 --- a/toonz/sources/toonzlib/fxcommand.cpp +++ b/toonz/sources/toonzlib/fxcommand.cpp @@ -1152,7 +1152,13 @@ void ReplaceFxUndo::initialize() { fx = zcfx->getZeraryFx(); } - if (has_fx_column(fx)) { + TZeraryColumnFx *zcrepfx = dynamic_cast(repFx); + if (zcrepfx) repFx = zcrepfx->getZeraryFx(); + + bool fxHasCol = has_fx_column(fx); + bool repfxHasCol = has_fx_column(repFx); + + if (fxHasCol && repfxHasCol) { if (zcfx) { // Build a column with the same source cells pattern m_repColumn = new TXshZeraryFxColumn(*zcfx->getColumn()); @@ -1170,6 +1176,10 @@ void ReplaceFxUndo::initialize() { m_repColIdx = xsh->getFirstFreeColumnIndex(); m_repFx = static_cast(m_repColumn->getFx()); } + } else if (!fxHasCol && repfxHasCol) { + m_repColumn = FxCommandUndo::createZeraryFxColumn(xsh, repFx); + m_repColIdx = xsh->getFirstFreeColumnIndex(); + m_repFx = static_cast(m_repColumn->getFx()); } FxCommandUndo::cloneGroupStack(fx, m_repFx.getPointer()); @@ -1598,7 +1608,8 @@ private: else { TOutputFx *currentOutputFx = xsh->getFxDag()->getCurrentOutputFx(); const TPointD &pos = currentOutputFx->getAttributes()->getDagNodePos(); - outputFx->getAttributes()->setDagNodePos(pos + TPointD(20, 20)); + if (pos != TConst::nowhere) + outputFx->getAttributes()->setDagNodePos(pos + TPointD(20, 20)); } } }; @@ -2637,7 +2648,8 @@ void UndoPasteFxs::initialize(const std::map &zeraryFxColumnSize, TFx *fx = *ft; const TPointD &fxPos = fx->getAttributes()->getDagNodePos(); - fx->getAttributes()->setDagNodePos(fxPos + offset); + if (fxPos != TConst::nowhere) + fx->getAttributes()->setDagNodePos(fxPos + offset); } } } diff --git a/toonz/sources/toonzlib/levelupdater.cpp b/toonz/sources/toonzlib/levelupdater.cpp index 59d364d..bc86051 100644 --- a/toonz/sources/toonzlib/levelupdater.cpp +++ b/toonz/sources/toonzlib/levelupdater.cpp @@ -342,7 +342,9 @@ TFilePath LevelUpdater::getNewTemporaryFilePath(const TFilePath &fp) { int count = 1; for (;;) { - fp2 = fp.withName(fp.getWideName() + L"__" + std::to_wstring(count++)); + // changed the temporary name as the previous naming (like + // "filename__1.png") had been misteken as sequential images + fp2 = fp.withName(fp.getWideName() + L"_ottmp" + std::to_wstring(count++)); if (!TSystem::doesExistFileOrLevel(fp2)) break; } diff --git a/toonz/sources/toonzlib/movierenderer.cpp b/toonz/sources/toonzlib/movierenderer.cpp index c11a4c2..1d8b306 100644 --- a/toonz/sources/toonzlib/movierenderer.cpp +++ b/toonz/sources/toonzlib/movierenderer.cpp @@ -20,6 +20,7 @@ #include "toonz/trasterimageutils.h" #include "toonz/levelupdater.h" #include "toutputproperties.h" +#include "toonz/boardsettings.h" // tcg includes #include "tcg/tcg_macros.h" @@ -160,6 +161,8 @@ public: std::pair saveFrame(double frame, const std::pair &rasters); std::string getRenderCacheId(); + + void addBoard(); }; //--------------------------------------------------------- @@ -374,7 +377,15 @@ std::pair MovieRenderer::Imp::saveFrame( m_renderSettings.m_timeStretchFrom; int fr = (stretchFac != 1) ? tround(frame * stretchFac) : int(frame); - TFrameId fid(fr + 1); + + int boardDuration = 0; + if (m_movieType) { + BoardSettings *bs = + m_scene->getProperties()->getOutputProperties()->getBoardSettings(); + boardDuration = (bs->isActive()) ? bs->getDuration() : 0; + } + + TFrameId fid(fr + 1 + boardDuration); if (m_levelUpdaterA.get()) { assert(m_levelUpdaterB.get() || !rasters.second); @@ -474,6 +485,8 @@ void MovieRenderer::Imp::doRenderRasterCompleted(const RenderData &renderData) { if (m_levelUpdaterB.get()) m_levelUpdaterB->getLevelWriter()->saveSoundTrack(m_st.getPointer()); } + + addBoard(); } // Output frames must be *cloned*, since the supplied rasters will be @@ -732,6 +745,40 @@ void MovieRenderer::Imp::onRenderFinished(bool isCanceled) { // eventually be deleted. } +//--------------------------------------------------------- + +void MovieRenderer::Imp::addBoard() { + BoardSettings *boardSettings = + m_scene->getProperties()->getOutputProperties()->getBoardSettings(); + if (!boardSettings->isActive()) return; + int duration = boardSettings->getDuration(); + if (duration == 0) return; + // Get the image size + int shrinkX = m_renderSettings.m_shrinkX, + shrinkY = m_renderSettings.m_shrinkY; + TDimensionD cameraRes(double(m_frameSize.lx) / shrinkX, + double(m_frameSize.ly) / shrinkY); + TDimension cameraResI(cameraRes.lx, cameraRes.ly); + + TRaster32P boardRas = + boardSettings->getBoardRaster(cameraResI, shrinkX, m_scene); + + if (m_levelUpdaterA.get()) { + // Flush images + try { + TRasterImageP img(boardRas); + for (int f = 0; f < duration; f++) { + m_levelUpdaterA->update(TFrameId(f + 1), img); + if (m_levelUpdaterB.get()) + m_levelUpdaterB->update(TFrameId(f + 1), img); + } + } catch (...) { + // Nothing. The images could not be saved for whatever reason. + // Failure is reported. + } + } +} + //====================================================================================== //====================== diff --git a/toonz/sources/toonzlib/onionskinmask.cpp b/toonz/sources/toonzlib/onionskinmask.cpp index 7a71ff8..0000031 100644 --- a/toonz/sources/toonzlib/onionskinmask.cpp +++ b/toonz/sources/toonzlib/onionskinmask.cpp @@ -64,6 +64,8 @@ void OnionSkinMask::clear() { m_ghostAff[1] = TAffine(); m_ghostCenter[0] = TPointD(); m_ghostCenter[1] = TPointD(); + m_ghostFrame[0] = 0; + m_ghostFrame[1] = 0; } //------------------------------------------------------------------- diff --git a/toonz/sources/toonzlib/orientation.cpp b/toonz/sources/toonzlib/orientation.cpp index b307f6a..d42fae0 100644 --- a/toonz/sources/toonzlib/orientation.cpp +++ b/toonz/sources/toonzlib/orientation.cpp @@ -10,15 +10,16 @@ using std::pair; namespace { -const int KEY_ICON_WIDTH = 11; -const int KEY_ICON_HEIGHT = 13; -const int EASE_TRIANGLE_SIZE = 4; -const int PLAY_MARKER_SIZE = 10; -const int ONION_SIZE = 19; -const int ONION_DOT_SIZE = 8; -const int PINNED_SIZE = 10; -const int FRAME_MARKER_SIZE = 4; -const int FOLDED_CELL_SIZE = 9; +const int KEY_ICON_WIDTH = 11; +const int KEY_ICON_HEIGHT = 13; +const int EASE_TRIANGLE_SIZE = 4; +const int PLAY_MARKER_SIZE = 10; +const int ONION_SIZE = 19; +const int ONION_DOT_SIZE = 8; +const int PINNED_SIZE = 10; +const int FRAME_MARKER_SIZE = 4; +const int FOLDED_CELL_SIZE = 9; +const int SHIFTTRACE_DOT_SIZE = 12; } class TopToBottomOrientation : public Orientation { @@ -34,9 +35,10 @@ class TopToBottomOrientation : public Orientation { const int FRAME_HEADER_WIDTH = CELL_WIDTH; const int PLAY_RANGE_X = FRAME_HEADER_WIDTH / 2 - PLAY_MARKER_SIZE; const int ONION_X = 0, ONION_Y = 0; - const int ICON_WIDTH = 18; - const int ICON_HEIGHT = 18; - const int TRACKLEN = 60; + const int ICON_WIDTH = 18; + const int ICON_HEIGHT = 18; + const int TRACKLEN = 60; + const int SHIFTTRACE_DOT_OFFSET = 3; public: TopToBottomOrientation(); @@ -78,8 +80,8 @@ public: class LeftToRightOrientation : public Orientation { const int CELL_WIDTH = 50; - const int CELL_HEIGHT = 20; - const int CELL_DRAG_HEIGHT = 5; + const int CELL_HEIGHT = 24; + const int CELL_DRAG_HEIGHT = 7; const int EXTENDER_WIDTH = 8; const int EXTENDER_HEIGHT = 12; const int SOUND_PREVIEW_HEIGHT = 6; @@ -90,13 +92,17 @@ class LeftToRightOrientation : public Orientation { const int ICON_HEIGHT = 20; const int ICON_OFFSET = ICON_WIDTH; const int ICONS_WIDTH = ICON_OFFSET * 4; // 88 + const int THUMBNAIL_WIDTH = 43; const int LAYER_NUMBER_WIDTH = 20; const int LAYER_NAME_WIDTH = 150; const int LAYER_HEADER_WIDTH = - ICONS_WIDTH + LAYER_NUMBER_WIDTH + LAYER_NAME_WIDTH; + ICONS_WIDTH + THUMBNAIL_WIDTH + LAYER_NUMBER_WIDTH + LAYER_NAME_WIDTH; const int FOLDED_LAYER_HEADER_HEIGHT = 8; const int FOLDED_LAYER_HEADER_WIDTH = LAYER_HEADER_WIDTH; const int TRACKLEN = 60; + const int SHIFTTRACE_DOT_OFFSET = 5; + const int LAYER_HEADER_PANEL_HEIGHT = 20; + const int LAYER_FOOTER_PANEL_HEIGHT = 16; public: LeftToRightOrientation(); @@ -312,7 +318,13 @@ TopToBottomOrientation::TopToBottomOrientation() { QRect(QPoint(0, 0), QSize(FRAME_HEADER_WIDTH, use_header_height - 1))); addRect(PredefinedRect::NOTE_ICON, QRect(QPoint(0, 0), QSize(CELL_WIDTH - 2, CELL_HEIGHT - 2))); - addRect(PredefinedRect::LAYER_HEADER_PANEL, QRect(0, 0, -1, -1)); // hide + + // Layer header panel + addRect(PredefinedRect::LAYER_HEADER_PANEL, QRect(0, 0, -1, -1)); // hide + addRect(PredefinedRect::PANEL_EYE, QRect(0, 0, -1, -1)); // hide + addRect(PredefinedRect::PANEL_PREVIEW_LAYER, QRect(0, 0, -1, -1)); // hide + addRect(PredefinedRect::PANEL_LOCK, QRect(0, 0, -1, -1)); // hide + addRect(PredefinedRect::PANEL_LAYER_NAME, QRect(0, 0, -1, -1)); // hide // Row viewer addRect(PredefinedRect::FRAME_LABEL, @@ -336,10 +348,10 @@ TopToBottomOrientation::TopToBottomOrientation() { addRect(PredefinedRect::ONION_AREA, QRect(ONION_X, ONION_Y, PLAY_RANGE_X, CELL_HEIGHT)); addRect(PredefinedRect::ONION_FIXED_DOT_AREA, - QRect(ONION_X, ONION_Y, ONION_DOT_SIZE, CELL_HEIGHT)); - addRect( - PredefinedRect::ONION_DOT_AREA, - QRect(ONION_X + ONION_DOT_SIZE, ONION_Y, ONION_DOT_SIZE, CELL_HEIGHT)); + QRect(ONION_X, ONION_Y, ONION_DOT_SIZE + 1, CELL_HEIGHT)); + addRect(PredefinedRect::ONION_DOT_AREA, + QRect(ONION_X + ONION_DOT_SIZE + 1, ONION_Y, ONION_DOT_SIZE + 1, + CELL_HEIGHT)); addRect(PredefinedRect::PINNED_CENTER_KEY, QRect((FRAME_HEADER_WIDTH - PINNED_SIZE) / 2, (CELL_HEIGHT - PINNED_SIZE) / 2, PINNED_SIZE, PINNED_SIZE)); @@ -347,6 +359,12 @@ TopToBottomOrientation::TopToBottomOrientation() { PredefinedRect::PREVIEW_FRAME_AREA, QRect(PLAY_RANGE_X, 0, (FRAME_HEADER_WIDTH - PLAY_RANGE_X), CELL_HEIGHT)); + addRect(PredefinedRect::SHIFTTRACE_DOT, + QRect(SHIFTTRACE_DOT_OFFSET, (CELL_HEIGHT - SHIFTTRACE_DOT_SIZE) / 2, + SHIFTTRACE_DOT_SIZE, SHIFTTRACE_DOT_SIZE)); + addRect(PredefinedRect::SHIFTTRACE_DOT_AREA, + QRect(SHIFTTRACE_DOT_OFFSET, 0, SHIFTTRACE_DOT_SIZE, CELL_HEIGHT)); + // Column viewer addRect(PredefinedRect::LAYER_HEADER, QRect(0, 1, CELL_WIDTH, use_header_height - 3)); @@ -433,9 +451,11 @@ TopToBottomOrientation::TopToBottomOrientation() { QRect(thumbnail.right() - 14, thumbnail.top() + 3, 12, 12)); addRect(PredefinedRect::SOUND_ICON, - QRect(thumbnailArea.topLeft(), QSize(27, 20)) - .adjusted((thumbnailArea.width() / 2) - (27 / 2), 3, - (thumbnailArea.width() / 2) - (27 / 2), 3)); + QRect(thumbnailArea.topLeft(), QSize(40, 30)) + .adjusted((thumbnailArea.width() / 2) - (40 / 2), + (thumbnailArea.height() / 2) - (30 / 2), + (thumbnailArea.width() / 2) - (40 / 2), + (thumbnailArea.height() / 2) - (30 / 2))); volumeArea = QRect(QPoint(thumbnailArea.left() + 3, thumbnailArea.bottom() - 16), @@ -536,9 +556,11 @@ TopToBottomOrientation::TopToBottomOrientation() { QRect(thumbnail.right() - 14, thumbnail.top() + 3, 12, 12)); addRect(PredefinedRect::SOUND_ICON, - QRect(thumbnailArea.topLeft(), QSize(27, 20)) - .adjusted((thumbnailArea.width() / 2) - (27 / 2), 3, - (thumbnailArea.width() / 2) - (27 / 2), 3)); + QRect(thumbnailArea.topLeft(), QSize(40, 30)) + .adjusted((thumbnailArea.width() / 2) - (40 / 2), + (thumbnailArea.height() / 2) - (30 / 2), + (thumbnailArea.width() / 2) - (40 / 2), + (thumbnailArea.height() / 2) - (30 / 2))); volumeArea = QRect(QPoint(thumbnailArea.left() + 3, thumbnailArea.bottom() - 16), @@ -879,15 +901,16 @@ LeftToRightOrientation::LeftToRightOrientation() { addRect(PredefinedRect::DRAG_HANDLE_CORNER, QRect(0, 0, CELL_WIDTH, CELL_DRAG_HEIGHT)); QRect keyRect((CELL_WIDTH - KEY_ICON_WIDTH) / 2, - CELL_HEIGHT - KEY_ICON_HEIGHT, KEY_ICON_WIDTH, KEY_ICON_HEIGHT); + CELL_HEIGHT - KEY_ICON_HEIGHT - 2, KEY_ICON_WIDTH, + KEY_ICON_HEIGHT); addRect(PredefinedRect::KEY_ICON, keyRect); QRect nameRect = cellRect.adjusted(4, 4, -6, 0); addRect(PredefinedRect::CELL_NAME, nameRect); addRect(PredefinedRect::CELL_NAME_WITH_KEYFRAME, nameRect); addRect(PredefinedRect::END_EXTENDER, - QRect(0, -EXTENDER_HEIGHT - 10, EXTENDER_WIDTH, EXTENDER_HEIGHT)); + QRect(0, -EXTENDER_HEIGHT - 14, EXTENDER_WIDTH, EXTENDER_HEIGHT)); addRect(PredefinedRect::BEGIN_EXTENDER, - QRect(-EXTENDER_WIDTH, -EXTENDER_HEIGHT - 10, EXTENDER_WIDTH, + QRect(-EXTENDER_WIDTH, -EXTENDER_HEIGHT - 14, EXTENDER_WIDTH, EXTENDER_HEIGHT)); addRect(PredefinedRect::KEYFRAME_AREA, keyRect); addRect(PredefinedRect::DRAG_AREA, QRect(0, 0, CELL_WIDTH, CELL_DRAG_HEIGHT)); @@ -904,7 +927,7 @@ LeftToRightOrientation::LeftToRightOrientation() { CELL_HEIGHT - CELL_DRAG_HEIGHT)); addRect(PredefinedRect::LOOP_ICON, QRect(0, keyRect.top(), 10, 11)); QRect frameMarker((CELL_WIDTH - FRAME_MARKER_SIZE) / 2 - 1, - CELL_HEIGHT - FRAME_MARKER_SIZE - 6, FRAME_MARKER_SIZE, + CELL_HEIGHT - FRAME_MARKER_SIZE - 7, FRAME_MARKER_SIZE, FRAME_MARKER_SIZE); addRect(PredefinedRect::FRAME_MARKER_AREA, frameMarker); @@ -914,9 +937,21 @@ LeftToRightOrientation::LeftToRightOrientation() { QRect(QPoint(0, 0), QSize(LAYER_HEADER_WIDTH - 1, FRAME_HEADER_HEIGHT))); addRect(PredefinedRect::NOTE_ICON, QRect(QPoint(0, 0), QSize(CELL_WIDTH - 2, CELL_HEIGHT - 2))); + + // Layer header panel addRect(PredefinedRect::LAYER_HEADER_PANEL, QRect(0, FRAME_HEADER_HEIGHT - CELL_HEIGHT, LAYER_HEADER_WIDTH, - CELL_HEIGHT)); + LAYER_HEADER_PANEL_HEIGHT)); + QRect panelEye(1, 0, ICON_WIDTH, ICON_HEIGHT); + addRect(PredefinedRect::PANEL_EYE, panelEye.adjusted(1, 1, -1, -1)); + addRect(PredefinedRect::PANEL_PREVIEW_LAYER, + panelEye.translated(ICON_OFFSET, 0).adjusted(1, 1, -1, -1)); + addRect(PredefinedRect::PANEL_LOCK, + panelEye.translated(2 * ICON_OFFSET, 0).adjusted(1, 1, -1, -1)); + QRect panelName(ICONS_WIDTH + THUMBNAIL_WIDTH + 1, 0, + LAYER_NAME_WIDTH + LAYER_NUMBER_WIDTH - 4, + LAYER_HEADER_PANEL_HEIGHT); + addRect(PredefinedRect::PANEL_LAYER_NAME, panelName); // Row viewer addRect(PredefinedRect::FRAME_LABEL, @@ -942,9 +977,10 @@ LeftToRightOrientation::LeftToRightOrientation() { addRect(PredefinedRect::ONION_AREA, QRect(ONION_X, ONION_Y, CELL_WIDTH, ONION_SIZE)); addRect(PredefinedRect::ONION_FIXED_DOT_AREA, - QRect(ONION_X, ONION_Y, CELL_WIDTH, ONION_DOT_SIZE)); + QRect(ONION_X, ONION_Y, CELL_WIDTH, ONION_DOT_SIZE + 1)); addRect(PredefinedRect::ONION_DOT_AREA, - QRect(ONION_X, ONION_Y + ONION_DOT_SIZE, CELL_WIDTH, ONION_DOT_SIZE)); + QRect(ONION_X, ONION_Y + ONION_DOT_SIZE + 1, CELL_WIDTH, + ONION_DOT_SIZE + 1)); addRect( PredefinedRect::PINNED_CENTER_KEY, QRect((CELL_WIDTH - PINNED_SIZE) / 2, @@ -953,66 +989,85 @@ LeftToRightOrientation::LeftToRightOrientation() { PredefinedRect::PREVIEW_FRAME_AREA, QRect(0, PLAY_RANGE_Y, CELL_WIDTH, (FRAME_HEADER_HEIGHT - PLAY_RANGE_Y))); + addRect(PredefinedRect::SHIFTTRACE_DOT, + QRect((CELL_WIDTH - SHIFTTRACE_DOT_SIZE) / 2, SHIFTTRACE_DOT_OFFSET, + SHIFTTRACE_DOT_SIZE, SHIFTTRACE_DOT_SIZE) + .adjusted(-1, 0, -1, 0)); + addRect(PredefinedRect::SHIFTTRACE_DOT_AREA, + QRect(0, SHIFTTRACE_DOT_OFFSET, CELL_WIDTH, SHIFTTRACE_DOT_SIZE)); + // Column viewer addRect(PredefinedRect::LAYER_HEADER, QRect(1, 0, LAYER_HEADER_WIDTH - 2, CELL_HEIGHT)); addRect( PredefinedRect::FOLDED_LAYER_HEADER, QRect(1, 0, FOLDED_LAYER_HEADER_WIDTH - 2, FOLDED_LAYER_HEADER_HEIGHT)); - QRect columnName(ICONS_WIDTH + 1, 0, + QRect columnName(ICONS_WIDTH + THUMBNAIL_WIDTH + 1, 0, LAYER_NAME_WIDTH + LAYER_NUMBER_WIDTH - 4, CELL_HEIGHT); addRect(PredefinedRect::RENAME_COLUMN, columnName); - QRect eye(1, 0, ICON_WIDTH, ICON_HEIGHT); - addRect(PredefinedRect::EYE_AREA, eye); + QRect eyeArea(1, 0, ICON_WIDTH, CELL_HEIGHT); + QRect eye(1, + eyeArea.top() + ((eyeArea.height() / 2) - ((ICON_HEIGHT - 1) / 2)), + ICON_WIDTH, ICON_HEIGHT); + addRect(PredefinedRect::EYE_AREA, eyeArea); addRect(PredefinedRect::EYE, eye.adjusted(1, 1, -1, -1)); - addRect(PredefinedRect::PREVIEW_LAYER_AREA, eye.translated(ICON_OFFSET, 0)); + addRect(PredefinedRect::PREVIEW_LAYER_AREA, + eyeArea.translated(ICON_OFFSET, 0)); addRect(PredefinedRect::PREVIEW_LAYER, eye.translated(ICON_OFFSET, 0).adjusted(1, 1, -1, -1)); - addRect(PredefinedRect::LOCK_AREA, eye.translated(2 * ICON_OFFSET, 0)); + addRect(PredefinedRect::LOCK_AREA, eyeArea.translated(2 * ICON_OFFSET, 0)); addRect(PredefinedRect::LOCK, eye.translated(2 * ICON_OFFSET, 0).adjusted(1, 1, -1, -1)); - addRect(PredefinedRect::CONFIG_AREA, eye.translated(3 * ICON_OFFSET, 0)); + addRect(PredefinedRect::CONFIG_AREA, eyeArea.translated(3 * ICON_OFFSET, 0)); addRect(PredefinedRect::CONFIG, eye.translated(3 * ICON_OFFSET, 0).adjusted(1, 1, -1, -1)); addRect(PredefinedRect::DRAG_LAYER, - QRect(ICONS_WIDTH + 1, 0, LAYER_HEADER_WIDTH - ICONS_WIDTH - 3, + QRect(ICONS_WIDTH + THUMBNAIL_WIDTH + 1, 0, + LAYER_HEADER_WIDTH - ICONS_WIDTH - THUMBNAIL_WIDTH - 3, CELL_DRAG_HEIGHT)); addRect(PredefinedRect::LAYER_NAME, columnName); addRect(PredefinedRect::LAYER_NUMBER, - QRect(ICONS_WIDTH + 1, 0, LAYER_NUMBER_WIDTH, CELL_HEIGHT)); - addRect(PredefinedRect::THUMBNAIL_AREA, QRect(0, 0, -1, -1)); // hide - addRect(PredefinedRect::THUMBNAIL, QRect(0, 0, -1, -1)); // hide + QRect(ICONS_WIDTH + THUMBNAIL_WIDTH + 1, 0, LAYER_NUMBER_WIDTH, + CELL_HEIGHT)); + QRect thumbnailArea = QRect(ICONS_WIDTH + 1, 0, THUMBNAIL_WIDTH, CELL_HEIGHT); + addRect(PredefinedRect::THUMBNAIL_AREA, thumbnailArea); + QRect thumbnail = thumbnailArea.adjusted(1, 1, 0, 0); + addRect(PredefinedRect::THUMBNAIL, thumbnail); addRect(PredefinedRect::FILTER_COLOR, - QRect(LAYER_HEADER_WIDTH - 17, 6, 12, 12)); + QRect(thumbnail.right() - 14, thumbnail.top() + 3, 12, 12)); addRect(PredefinedRect::PEGBAR_NAME, QRect(0, 0, -1, -1)); // hide addRect(PredefinedRect::PARENT_HANDLE_NAME, QRect(0, 0, -1, -1)); // hide addRect(PredefinedRect::SOUND_ICON, - QRect(columnName.topRight(), QSize(27, columnName.height())) - .adjusted(-28, 0, -28, 0)); + QRect(thumbnailArea.topLeft(), QSize(27, thumbnailArea.height())) + .adjusted((thumbnailArea.width() / 2) - (27 / 2), 0, + (thumbnailArea.width() / 2) - (27 / 2), 0)); - QRect volumeArea(QRect(columnName.topRight(), QSize(TRACKLEN + 8, 14)) - .adjusted(-97, 4, -97, 4)); + QRect volumeArea( + QRect(columnName.topRight(), QSize(TRACKLEN + 8, 14)) + .adjusted(-77, CELL_DRAG_HEIGHT + 1, -77, CELL_DRAG_HEIGHT + 1)); addRect(PredefinedRect::VOLUME_AREA, volumeArea); QPoint soundTopLeft(volumeArea.left() + 4, volumeArea.bottom() - 6); addRect(PredefinedRect::VOLUME_TRACK, QRect(soundTopLeft, QSize(TRACKLEN, 3))); // Layer footer panel - QRect layerFooterPanel(QRect(0, 0, LAYER_HEADER_WIDTH + 2, 16)); + QRect layerFooterPanel( + QRect(0, 0, LAYER_HEADER_WIDTH + 2, LAYER_FOOTER_PANEL_HEIGHT)); addRect(PredefinedRect::LAYER_FOOTER_PANEL, layerFooterPanel); QRect zoomSlider, zoomIn, zoomOut; - zoomSlider = QRect(layerFooterPanel.width() - 100, 0, 81, 16); + zoomSlider = + QRect(layerFooterPanel.width() - 100, 0, 81, LAYER_FOOTER_PANEL_HEIGHT); addRect(PredefinedRect::ZOOM_SLIDER_AREA, zoomSlider); addRect(PredefinedRect::ZOOM_SLIDER, zoomSlider.adjusted(1, 0, 0, 0)); - zoomIn = QRect(zoomSlider.right() + 1, 0, 16, 16); + zoomIn = QRect(zoomSlider.right() + 1, 0, 16, LAYER_FOOTER_PANEL_HEIGHT); addRect(PredefinedRect::ZOOM_IN_AREA, zoomIn); addRect(PredefinedRect::ZOOM_IN, zoomIn.adjusted(1, 1, 0, 0)); - zoomOut = QRect(zoomSlider.left() - 16, 0, 16, 16); + zoomOut = QRect(zoomSlider.left() - 16, 0, 16, LAYER_FOOTER_PANEL_HEIGHT); addRect(PredefinedRect::ZOOM_OUT_AREA, zoomOut); addRect(PredefinedRect::ZOOM_OUT, zoomOut.adjusted(1, 1, 0, 0)); @@ -1035,8 +1090,8 @@ LeftToRightOrientation::LeftToRightOrientation() { addFlag(PredefinedFlag::PEGBAR_NAME_VISIBLE, false); addFlag(PredefinedFlag::PARENT_HANDLE_NAME_BORDER, false); addFlag(PredefinedFlag::PARENT_HANDLE_NAME_VISIBILE, false); - addFlag(PredefinedFlag::THUMBNAIL_AREA_BORDER, false); - addFlag(PredefinedFlag::THUMBNAIL_AREA_VISIBLE, false); + addFlag(PredefinedFlag::THUMBNAIL_AREA_BORDER, true); + addFlag(PredefinedFlag::THUMBNAIL_AREA_VISIBLE, true); addFlag(PredefinedFlag::VOLUME_AREA_VERTICAL, false); // diff --git a/toonz/sources/toonzlib/outputproperties.cpp b/toonz/sources/toonzlib/outputproperties.cpp index 0ea61b2..2b90dde 100644 --- a/toonz/sources/toonzlib/outputproperties.cpp +++ b/toonz/sources/toonzlib/outputproperties.cpp @@ -2,6 +2,9 @@ #include "toutputproperties.h" +// TnzLib includes +#include "toonz/boardsettings.h" + // TnzBase includes #include "trasterfx.h" @@ -37,7 +40,8 @@ TOutputProperties::TOutputProperties() , m_multimediaRendering(0) , m_maxTileSizeIndex(0) , m_threadIndex(2) - , m_subcameraPreview(false) { + , m_subcameraPreview(false) + , m_boardSettings(new BoardSettings()) { m_renderSettings = new TRenderSettings(); } @@ -56,7 +60,8 @@ TOutputProperties::TOutputProperties(const TOutputProperties &src) , m_multimediaRendering(src.m_multimediaRendering) , m_maxTileSizeIndex(src.m_maxTileSizeIndex) , m_threadIndex(src.m_threadIndex) - , m_subcameraPreview(src.m_subcameraPreview) { + , m_subcameraPreview(src.m_subcameraPreview) + , m_boardSettings(new BoardSettings(*src.m_boardSettings)) { std::map::iterator ft, fEnd = m_formatProperties.end(); for (ft = m_formatProperties.begin(); ft != fEnd; ++ft) { @@ -100,6 +105,9 @@ TOutputProperties &TOutputProperties::operator=(const TOutputProperties &src) { for (sft = src.m_formatProperties.begin(); sft != sfEnd; ++sft) m_formatProperties[sft->first] = sft->second->clone(); + delete m_boardSettings; + m_boardSettings = new BoardSettings(*src.m_boardSettings); + return *this; } diff --git a/toonz/sources/toonzlib/palettecmd.cpp b/toonz/sources/toonzlib/palettecmd.cpp index bd8a16f..a133a47 100644 --- a/toonz/sources/toonzlib/palettecmd.cpp +++ b/toonz/sources/toonzlib/palettecmd.cpp @@ -13,11 +13,9 @@ #include "toonz/txshlevelcolumn.h" #include "toonz/txshsimplelevel.h" #include "toonz/cleanupcolorstyles.h" -#include "toonz/studiopalette.h" #include "toonz/txshlevel.h" #include "toonz/toonzscene.h" #include "toonz/toonzimageutils.h" -#include "toonz/cleanupcolorstyles.h" #include "toonz/preferences.h" // TnzCore includes diff --git a/toonz/sources/toonzlib/preferences.cpp b/toonz/sources/toonzlib/preferences.cpp index 85a0b1a..79b498b 100644 --- a/toonz/sources/toonzlib/preferences.cpp +++ b/toonz/sources/toonzlib/preferences.cpp @@ -19,6 +19,7 @@ #include "tundo.h" #include "tbigmemorymanager.h" #include "tfilepath.h" +#include "timage_io.h" // Qt includes #include @@ -231,6 +232,7 @@ Preferences::Preferences() #else , m_interfaceFont("Helvetica") #endif + , m_interfaceFontStyle("Regular") , m_interfaceFontWeight(0) , m_defLevelWidth(0.0) , m_defLevelHeight(0.0) @@ -342,7 +344,10 @@ Preferences::Preferences() , m_cursorBrushType("Small") , m_cursorBrushStyle("Default") , m_cursorOutlineEnabled(true) - , m_currentColumnColor(TPixel::Black) { + , m_currentColumnColor(TPixel::Black) + , m_enableWinInk(false) + , m_useOnionColorsForShiftAndTraceGhosts(false) + , m_rasterBackgroundColor(TPixel::White) { TCamera camera; m_defLevelType = PLI_XSHLEVEL; m_defLevelWidth = camera.getSize().lx; @@ -618,6 +623,8 @@ Preferences::Preferences() m_moveCurrentFrameByClickCellArea); getValue(*m_settings, "onionSkinEnabled", m_onionSkinEnabled); getValue(*m_settings, "onionSkinDuringPlayback", m_onionSkinDuringPlayback); + getValue(*m_settings, "useOnionColorsForShiftAndTraceGhosts", + m_useOnionColorsForShiftAndTraceGhosts); getValue(*m_settings, "multiLayerStylePickerEnabled", m_multiLayerStylePickerEnabled); getValue(*m_settings, "showKeyframesOnXsheetCellArea", @@ -635,6 +642,10 @@ Preferences::Preferences() QString interfaceFont = m_settings->value("interfaceFont").toString(); if (interfaceFont != "") m_interfaceFont = interfaceFont; setInterfaceFont(m_interfaceFont.toStdString()); + QString interfaceFontStyle = + m_settings->value("interfaceFontStyle").toString(); + if (interfaceFontStyle != "") m_interfaceFontStyle = interfaceFontStyle; + setInterfaceFontStyle(m_interfaceFontStyle.toStdString()); getValue(*m_settings, "interfaceFontWeight", m_interfaceFontWeight); getValue(*m_settings, "useNumpadForSwitchingStyles", m_useNumpadForSwitchingStyles); @@ -705,11 +716,16 @@ Preferences::Preferences() getValue(*m_settings, "cursorOutlineEnabled", m_cursorOutlineEnabled); - r = 255, g = 0, b = 0; + r = 255, g = 255, b = 0; getValue(*m_settings, "currentColumnColor.r", r); getValue(*m_settings, "currentColumnColor.g", g); getValue(*m_settings, "currentColumnColor.b", b); m_currentColumnColor = TPixel32(r, g, b); + + getValue(*m_settings, "winInkEnabled", m_enableWinInk); + + getValue(*m_settings, "rasterBackgroundColor", m_rasterBackgroundColor); + TImageWriter::setBackgroundColor(m_rasterBackgroundColor); } //----------------------------------------------------------------- @@ -1099,6 +1115,13 @@ void Preferences::setOnionSkinDuringPlayback(bool on) { //----------------------------------------------------------------- +void Preferences::useOnionColorsForShiftAndTraceGhosts(bool on) { + m_useOnionColorsForShiftAndTraceGhosts = on; + m_settings->setValue("useOnionColorsForShiftAndTraceGhosts", on ? "1" : "0"); +} + +//----------------------------------------------------------------- + void Preferences::setShow0ThickLines(bool on) { m_show0ThickLines = on; m_settings->setValue(s_show0ThickLines, s_bool[on]); @@ -1319,6 +1342,13 @@ void Preferences::setInterfaceFont(std::string font) { //----------------------------------------------------------------- +void Preferences::setInterfaceFontStyle(std::string style) { + m_interfaceFontStyle = QString::fromStdString(style); + m_settings->setValue("interfaceFontStyle", m_interfaceFontStyle); +} + +//----------------------------------------------------------------- + void Preferences::setInterfaceFontWeight(int weight) { m_interfaceFontWeight = weight; m_settings->setValue("interfaceFontWeight", m_interfaceFontWeight); @@ -1573,7 +1603,7 @@ void Preferences::setGuidedDrawing(int status) { void Preferences::setAnimatedGuidedDrawing(bool status) { m_animatedGuidedDrawing = status; - m_settings->setValue("animatedGuidedDrawing", status); + m_settings->setValue("animatedGuidedDrawing", status ? "1" : "0"); } //----------------------------------------------------------------- @@ -1725,3 +1755,21 @@ void Preferences::setCurrentColumnData(const TPixel ¤tColumnColor) { m_settings->setValue("currentColumnColor.b", QString::number(currentColumnColor.b)); } + +void Preferences::enableWinInk(bool on) { + m_enableWinInk = on; + m_settings->setValue("winInkEnabled", on ? "1" : "0"); +} + +void Preferences::setRasterBackgroundColor(const TPixel32 &color) { + m_rasterBackgroundColor = color; + TImageWriter::setBackgroundColor(m_rasterBackgroundColor); + m_settings->setValue("rasterBackgroundColor_R", + QString::number((int)color.r)); + m_settings->setValue("rasterBackgroundColor_G", + QString::number((int)color.g)); + m_settings->setValue("rasterBackgroundColor_B", + QString::number((int)color.b)); + m_settings->setValue("rasterBackgroundColor_M", + QString::number((int)color.m)); +} \ No newline at end of file diff --git a/toonz/sources/toonzlib/sandor_fxs/YOMBParam.cpp b/toonz/sources/toonzlib/sandor_fxs/YOMBParam.cpp index 4c86850..d42b73b 100644 --- a/toonz/sources/toonzlib/sandor_fxs/YOMBParam.cpp +++ b/toonz/sources/toonzlib/sandor_fxs/YOMBParam.cpp @@ -18,7 +18,6 @@ #include "STColSelPic.h" #include "BlurMatrix.h" #include "SDef.h" -#include "STColSelPic.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/toonz/sources/toonzlib/sandor_fxs/blend.cpp b/toonz/sources/toonzlib/sandor_fxs/blend.cpp index e84116c..6939ee5 100644 --- a/toonz/sources/toonzlib/sandor_fxs/blend.cpp +++ b/toonz/sources/toonzlib/sandor_fxs/blend.cpp @@ -654,8 +654,8 @@ void blend(TToonzImageP ti, TRasterPT rasOut, selectionRaster.updateSelection(cmIn, params[i]); doBlend(cmIn, inkLayer, paintLayer, selectionRaster, blurGroup[i]); - tswap(inkLayer.first, inkLayer.second); - tswap(paintLayer.first, paintLayer.second); + std::swap(inkLayer.first, inkLayer.second); + std::swap(paintLayer.first, paintLayer.second); } // Release the unnecessary rasters diff --git a/toonz/sources/toonzlib/scenefx.cpp b/toonz/sources/toonzlib/scenefx.cpp index e903d80..64672fb 100644 --- a/toonz/sources/toonzlib/scenefx.cpp +++ b/toonz/sources/toonzlib/scenefx.cpp @@ -28,8 +28,11 @@ #include "toonz/stage.h" #include "toonz/preferences.h" #include "ttzpimagefx.h" +#include "toonz/txshsoundtextcolumn.h" +#include "toonz/txshsoundtextlevel.h" #include "../stdfx/motionawarebasefx.h" +#include "../stdfx/textawarebasefx.h" #include "toonz/scenefx.h" @@ -497,6 +500,26 @@ static QList getColumnMotionPoints(TXsheet *xsh, double row, int col, return points; } +namespace { + +QString getNoteText(TXsheet *xsh, double row, int col, int noteColumnIndex, + bool neighbor) { + int colIndex; + if (neighbor) + colIndex = col - 1; + else + colIndex = noteColumnIndex; + + TXshColumn *column = xsh->getColumn(colIndex); + if (!column || !column->getSoundTextColumn()) return QString(); + + TXshCell cell = xsh->getCell(row, colIndex); + if (cell.isEmpty() || !cell.getSoundTextLevel()) return QString(); + + return cell.getSoundTextLevel()->getFrameText(cell.m_frameId.getNumber() - 1); +} +}; + //*************************************************************************************************** // FxBuilder definition //*************************************************************************************************** @@ -939,6 +962,18 @@ PlacedFx FxBuilder::makePF(TZeraryColumnFx *zcfx) { } } + if (pf.m_fx->getFxType() == "STD_iwa_TextFx") { + TextAwareBaseFx *textFx = + dynamic_cast(pf.m_fx.getPointer()); + if (textFx && textFx->getSourceType() != TextAwareBaseFx::INPUT_TEXT) { + int noteColumnIndex = textFx->getNoteColumnIndex(); + bool getNeighbor = + (textFx->getSourceType() == TextAwareBaseFx::NEARBY_COLUMN); + textFx->setNoteLevelStr(getNoteText(m_xsh, m_frame, pf.m_columnIndex, + noteColumnIndex, getNeighbor)); + } + } + // Add the column placement NaAffineFx if (getColumnPlacement(pf, m_xsh, m_frame, pf.m_columnIndex, m_isPreview)) return pf; diff --git a/toonz/sources/toonzlib/sceneproperties.cpp b/toonz/sources/toonzlib/sceneproperties.cpp index acf0699..7bc3c59 100644 --- a/toonz/sources/toonzlib/sceneproperties.cpp +++ b/toonz/sources/toonzlib/sceneproperties.cpp @@ -11,6 +11,7 @@ #include "toonz/txshleveltypes.h" #include "toonz/preferences.h" #include "cleanuppalette.h" +#include "toonz/boardsettings.h" // TnzBase includes #include "toutputproperties.h" @@ -293,6 +294,12 @@ void TSceneProperties::saveData(TOStream &os) const { } os.closeChild(); + if (out.getBoardSettings() && out.getBoardSettings()->getDuration()) { + os.openChild("clapperboardSettings"); + out.getBoardSettings()->saveData(os); + os.closeChild(); + } + os.closeChild(); // } os.closeChild(); @@ -654,6 +661,9 @@ void TSceneProperties::loadData(TIStream &is, bool isLoadingProject) { } else throw TException("unexpected tag: " + tagName); } // end while + } else if (tagName == "clapperboardSettings") { + assert(out.getBoardSettings()); + out.getBoardSettings()->loadData(is); } else { throw TException("unexpected property tag: " + tagName); } diff --git a/toonz/sources/toonzlib/scriptbinding.cpp b/toonz/sources/toonzlib/scriptbinding.cpp index 6a4de11..aa9850d 100644 --- a/toonz/sources/toonzlib/scriptbinding.cpp +++ b/toonz/sources/toonzlib/scriptbinding.cpp @@ -25,7 +25,6 @@ #include "tvectorrenderdata.h" #include "tgeometry.h" #include "toonz/stage.h" -#include "toonz/tcamera.h" #include "toonz/txshleveltypes.h" #include "toonz/levelproperties.h" #include "toonz/toonzscene.h" diff --git a/toonz/sources/toonzlib/scriptbinding_level.cpp b/toonz/sources/toonzlib/scriptbinding_level.cpp index 89864e3..4185bbb 100644 --- a/toonz/sources/toonzlib/scriptbinding_level.cpp +++ b/toonz/sources/toonzlib/scriptbinding_level.cpp @@ -17,7 +17,6 @@ #include "tvectorrenderdata.h" #include "tgeometry.h" #include "toonz/stage.h" -#include "toonz/tcamera.h" #include "toonz/txshleveltypes.h" #include "toonz/levelproperties.h" #include "toonz/toonzscene.h" @@ -27,7 +26,6 @@ #include "tsystem.h" #include #include -#include "tfiletype.h" namespace TScriptBinding { diff --git a/toonz/sources/toonzlib/stage.cpp b/toonz/sources/toonzlib/stage.cpp index cb9be4a..987771e 100644 --- a/toonz/sources/toonzlib/stage.cpp +++ b/toonz/sources/toonzlib/stage.cpp @@ -398,23 +398,45 @@ void StageBuilder::addCell(PlayerSet &players, ToonzScene *scene, TXsheet *xsh, } if (m_shiftTraceGhostId != NO_GHOST) { - if (m_shiftTraceGhostId != TRACED) player.m_opacity = 127; - int opacity = player.m_opacity; - player.m_bingoOrder = 10; - if (m_onionSkinMask.getShiftTraceStatus() != - OnionSkinMask::ENABLED_WITHOUT_GHOST_MOVEMENTS) { - if (m_shiftTraceGhostId == FIRST_GHOST) { - player.m_opacity = 30; + // if F1, F2 or F3 key is pressed, then draw only the corresponding ghost + int flipKey = m_onionSkinMask.getGhostFlipKey(); + if (Qt::Key_F1 <= flipKey && flipKey <= Qt::Key_F3) { + if (m_shiftTraceGhostId == TRACED && flipKey == Qt::Key_F2) { players.push_back(player); - player.m_opacity = opacity; + } else if (m_shiftTraceGhostId == FIRST_GHOST && + flipKey == Qt::Key_F1) { player.m_placement = m_onionSkinMask.getShiftTraceGhostAff(0) * player.m_placement; - } else if (m_shiftTraceGhostId == SECOND_GHOST) { - player.m_opacity = 30; players.push_back(player); - player.m_opacity = opacity; + } else if (m_shiftTraceGhostId == SECOND_GHOST && + flipKey == Qt::Key_F3) { player.m_placement = m_onionSkinMask.getShiftTraceGhostAff(1) * player.m_placement; + players.push_back(player); + } + return; + } + + else { + int opacity = player.m_opacity; + player.m_bingoOrder = 10; + if (m_onionSkinMask.getShiftTraceStatus() != + OnionSkinMask::ENABLED_WITHOUT_GHOST_MOVEMENTS) { + if (m_shiftTraceGhostId == FIRST_GHOST) { + player.m_opacity = 30; + players.push_back(player); + player.m_opacity = opacity; + player.m_onionSkinDistance = -1; + player.m_placement = + m_onionSkinMask.getShiftTraceGhostAff(0) * player.m_placement; + } else if (m_shiftTraceGhostId == SECOND_GHOST) { + player.m_opacity = 30; + players.push_back(player); + player.m_opacity = opacity; + player.m_onionSkinDistance = 1; + player.m_placement = + m_onionSkinMask.getShiftTraceGhostAff(1) * player.m_placement; + } } } } @@ -509,37 +531,46 @@ void StageBuilder::addCellWithOnionSkin(PlayerSet &players, ToonzScene *scene, } }; // locals - if (m_onionSkinMask.isShiftTraceEnabled() && col == m_currentColumnIndex) { - TXshCell cell = xsh->getCell(row, col); - int r = row - 1; - - // r,col can be a hold. find its starting point - for (; r - 1 >= 0 && xsh->getCell(r - 1, col) == cell; r--) - ; - if (cell.isEmpty()) r--; - - if (r >= 0 && - (cell.getSimpleLevel() == 0 || - xsh->getCell(r, col).getSimpleLevel() == cell.getSimpleLevel())) { - m_shiftTraceGhostId = FIRST_GHOST; - addCell(players, scene, xsh, r, col, level); - } - - TXshCell otherCell; - if (cell.getSimpleLevel() != 0) { - for (r = row + 1; (otherCell = xsh->getCell(r, col)) == cell; r++) - ; + if (m_onionSkinMask.isShiftTraceEnabled()) { + if (col == m_currentColumnIndex) { + TXshCell cell = xsh->getCell(row, col); + + // First Ghost + int r; + r = row + m_onionSkinMask.getShiftTraceGhostFrameOffset(0); + if (r >= 0 && xsh->getCell(r, col) != cell && + (cell.getSimpleLevel() == 0 || + xsh->getCell(r, col).getSimpleLevel() == cell.getSimpleLevel())) { + m_shiftTraceGhostId = FIRST_GHOST; + addCell(players, scene, xsh, r, col, level); + } - if (cell.getSimpleLevel() == 0 || - otherCell.getSimpleLevel() == cell.getSimpleLevel()) { + r = row + m_onionSkinMask.getShiftTraceGhostFrameOffset(1); + if (r >= 0 && xsh->getCell(r, col) != cell && + (cell.getSimpleLevel() == 0 || + xsh->getCell(r, col).getSimpleLevel() == cell.getSimpleLevel())) { m_shiftTraceGhostId = SECOND_GHOST; addCell(players, scene, xsh, r, col, level); } + + // draw current working frame + if (!cell.isEmpty()) { + m_shiftTraceGhostId = TRACED; + addCell(players, scene, xsh, row, col, level); + m_shiftTraceGhostId = NO_GHOST; + } } - if (!cell.isEmpty()) { - m_shiftTraceGhostId = TRACED; - addCell(players, scene, xsh, row, col, level); - m_shiftTraceGhostId = NO_GHOST; + // flip non-current columns as well + else { + int flipKey = m_onionSkinMask.getGhostFlipKey(); + if (flipKey == Qt::Key_F1) { + int r = row + m_onionSkinMask.getShiftTraceGhostFrameOffset(0); + addCell(players, scene, xsh, r, col, level); + } else if (flipKey == Qt::Key_F3) { + int r = row + m_onionSkinMask.getShiftTraceGhostFrameOffset(1); + addCell(players, scene, xsh, r, col, level); + } else + addCell(players, scene, xsh, row, col, level); } } else if (locals::doStandardOnionSkin(this, xsh, level, col)) { std::vector rows; @@ -632,10 +663,74 @@ void StageBuilder::addFrame(PlayerSet &players, ToonzScene *scene, TXsheet *xsh, void StageBuilder::addSimpleLevelFrame(PlayerSet &players, TXshSimpleLevel *level, const TFrameId &fid) { + auto addGhost = [&](int ghostIndex, int ghostRow, bool fullOpac = false) { + const TFrameId &ghostFid = level->index2fid(ghostRow); + + Player player; + player.m_sl = level; + player.m_frame = level->guessIndex(ghostFid); + player.m_fid = ghostFid; + player.m_isCurrentColumn = true; + player.m_isCurrentXsheetLevel = true; + player.m_isEditingLevel = true; + player.m_currentFrameId = m_currentFrameId; + player.m_isGuidedDrawingEnabled = m_isGuidedDrawingEnabled; + player.m_isVisibleinOSM = ghostRow >= 0; + player.m_onionSkinDistance = m_onionSkinDistance; + player.m_dpiAff = getDpiAffine(level, ghostFid); + player.m_ancestorColumnIndex = -1; + + if (fullOpac) { + player.m_placement = m_onionSkinMask.getShiftTraceGhostAff(ghostIndex) * + player.m_placement; + players.push_back(player); + return; + } + + int opacity = player.m_opacity; + player.m_bingoOrder = 10; + if (m_onionSkinMask.getShiftTraceStatus() != + OnionSkinMask::ENABLED_WITHOUT_GHOST_MOVEMENTS) { + player.m_opacity = 30; + players.push_back(player); + player.m_opacity = opacity; + player.m_onionSkinDistance = (ghostIndex == 0) ? -1 : 1; + player.m_placement = m_onionSkinMask.getShiftTraceGhostAff(ghostIndex) * + player.m_placement; + } + players.push_back(player); + }; + int index = -1; int row = level->guessIndex(fid); - if (!m_onionSkinMask.isEmpty() && m_onionSkinMask.isEnabled()) { + + // Shift & Trace + if (m_onionSkinMask.isShiftTraceEnabled()) { + int previousOffset = m_onionSkinMask.getShiftTraceGhostFrameOffset(0); + int forwardOffset = m_onionSkinMask.getShiftTraceGhostFrameOffset(1); + + // If F1, F2 or F3 key is pressed, then only + // display the corresponding ghost + int flipKey = m_onionSkinMask.getGhostFlipKey(); + if (Qt::Key_F1 <= flipKey && flipKey <= Qt::Key_F3) { + if (flipKey == Qt::Key_F1 && previousOffset != 0) { + addGhost(0, row + previousOffset, true); + return; + } else if (flipKey == Qt::Key_F3 && forwardOffset != 0) { + addGhost(1, row + forwardOffset, true); + return; + } + } + + else { + // draw the first ghost + if (previousOffset != 0) addGhost(0, row + previousOffset); + if (forwardOffset != 0) addGhost(1, row + forwardOffset); + } + } + // Onion Skin + else if (!m_onionSkinMask.isEmpty() && m_onionSkinMask.isEnabled()) { std::vector rows; m_onionSkinMask.getAll(row, rows); @@ -747,10 +842,11 @@ void Stage::visit(Visitor &visitor, const VisitArgs &args) { sb.m_onionSkinMask = *osm; sb.m_currentFrameId = args.m_currentFrameId; sb.m_isGuidedDrawingEnabled = args.m_isGuidedDrawingEnabled; - Player::m_onionSkinFrontSize = 0; - Player::m_onionSkinBackSize = 0; - Player::m_firstBackOnionSkin = 0; - Player::m_lastBackVisibleSkin = 0; + Player::m_onionSkinFrontSize = 0; + Player::m_onionSkinBackSize = 0; + Player::m_firstBackOnionSkin = 0; + Player::m_lastBackVisibleSkin = 0; + Player::m_isShiftAndTraceEnabled = osm->isShiftTraceEnabled(); sb.addFrame(sb.m_players, scene, xsh, row, 0, args.m_onlyVisible, args.m_checkPreviewVisibility); @@ -782,14 +878,15 @@ void Stage::visit(Visitor &visitor, TXshSimpleLevel *level, const TFrameId &fid, const OnionSkinMask &osm, bool isPlaying, int isGuidedDrawingEnabled) { StageBuilder sb; - sb.m_vs = &visitor.m_vs; - sb.m_onionSkinMask = osm; - sb.m_currentFrameId = fid; - sb.m_isGuidedDrawingEnabled = isGuidedDrawingEnabled; - Player::m_onionSkinFrontSize = 0; - Player::m_onionSkinBackSize = 0; - Player::m_firstBackOnionSkin = 0; - Player::m_lastBackVisibleSkin = 0; + sb.m_vs = &visitor.m_vs; + sb.m_onionSkinMask = osm; + sb.m_currentFrameId = fid; + sb.m_isGuidedDrawingEnabled = isGuidedDrawingEnabled; + Player::m_onionSkinFrontSize = 0; + Player::m_onionSkinBackSize = 0; + Player::m_firstBackOnionSkin = 0; + Player::m_lastBackVisibleSkin = 0; + Player::m_isShiftAndTraceEnabled = osm.isShiftTraceEnabled(); sb.addSimpleLevelFrame(sb.m_players, level, fid); updateOnionSkinSize(sb.m_players); sb.visit(sb.m_players, visitor, isPlaying); diff --git a/toonz/sources/toonzlib/stageplayer.cpp b/toonz/sources/toonzlib/stageplayer.cpp index f7ea268..2f7ff4e 100644 --- a/toonz/sources/toonzlib/stageplayer.cpp +++ b/toonz/sources/toonzlib/stageplayer.cpp @@ -19,10 +19,11 @@ using namespace Stage; // Stage::Player implementation //***************************************************************************************** -double Player::m_onionSkinFrontSize = 0; -double Player::m_onionSkinBackSize = 0; -double Player::m_firstBackOnionSkin = 0; -double Player::m_lastBackVisibleSkin = 0; +double Player::m_onionSkinFrontSize = 0; +double Player::m_onionSkinBackSize = 0; +double Player::m_firstBackOnionSkin = 0; +double Player::m_lastBackVisibleSkin = 0; +bool Player::m_isShiftAndTraceEnabled = false; //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonzlib/stagevisitor.cpp b/toonz/sources/toonzlib/stagevisitor.cpp index eaf3b4d..58784ee 100644 --- a/toonz/sources/toonzlib/stagevisitor.cpp +++ b/toonz/sources/toonzlib/stagevisitor.cpp @@ -49,6 +49,7 @@ #include "toonz/txshleveltypes.h" #include "imagebuilders.h" #include "toonz/tframehandle.h" +#include "toonz/preferences.h" // Qt includes #include @@ -228,6 +229,12 @@ void Picker::setDistance(double d) { m_minDist2 = d * d; } //----------------------------------------------------------------------------- void Picker::onImage(const Stage::Player &player) { + // if m_currentColumnIndex is other than the default value (-1), + // then pick only the current column. + if (m_currentColumnIndex != -1 && + m_currentColumnIndex != player.m_ancestorColumnIndex) + return; + bool picked = false; TAffine aff = m_viewAff * player.m_placement; TPointD point = aff.inv() * m_point; @@ -815,7 +822,9 @@ void RasterPainter::onVectorImage(TVectorImage *vi, if (player.m_onionSkinDistance != c_noOnionSkin) { TPixel32 frontOnionColor, backOnionColor; - if (player.m_onionSkinDistance != 0) { + if (player.m_onionSkinDistance != 0 && + (!player.m_isShiftAndTraceEnabled || + Preferences::instance()->areOnionColorsUsedForShiftAndTraceGhosts())) { prefs.getOnionData(frontOnionColor, backOnionColor, inksOnly); bgColor = (player.m_onionSkinDistance < 0) ? backOnionColor : frontOnionColor; @@ -916,10 +925,11 @@ void RasterPainter::onVectorImage(TVectorImage *vi, vi->selectFill(vi->getBBox(), 0, 1, true, true, false); } + TStroke *guidedStroke = 0; if (m_maskLevel > 0) tglDrawMask(rd, vi); else - tglDraw(rd, vi); + tglDraw(rd, vi, &guidedStroke); if (tc & ToonzCheck::eAutoclose) drawAutocloses(vi, rd); @@ -928,6 +938,8 @@ void RasterPainter::onVectorImage(TVectorImage *vi, delete cf; delete guidedCf; + + if (guidedStroke) m_guidedStrokes.push_back(guidedStroke); } //----------------------------------------------------- @@ -961,11 +973,17 @@ void RasterPainter::onRasterImage(TRasterImage *ri, ? 0.9 : (1.0 - OnionSkinMask::getOnionSkinFade( player.m_onionSkinDistance)); - alpha = tcrop(tround(onionSkiFade * 255.0), 0, 255); - onionMode = (player.m_onionSkinDistance > 0) - ? Node::eOnionSkinFront - : ((player.m_onionSkinDistance < 0) ? Node::eOnionSkinBack - : Node::eOnionSkinNone); + alpha = tcrop(tround(onionSkiFade * 255.0), 0, 255); + if (player.m_isShiftAndTraceEnabled && + !Preferences::instance()->areOnionColorsUsedForShiftAndTraceGhosts()) + onionMode = Node::eOnionSkinNone; + else { + onionMode = + (player.m_onionSkinDistance > 0) + ? Node::eOnionSkinFront + : ((player.m_onionSkinDistance < 0) ? Node::eOnionSkinBack + : Node::eOnionSkinNone); + } } else if (player.m_opacity < 255) alpha = player.m_opacity; TXshSimpleLevel *sl = player.m_sl; @@ -1018,11 +1036,19 @@ void RasterPainter::onToonzImage(TToonzImage *ti, const Stage::Player &player) { ? 0.9 : (1.0 - OnionSkinMask::getOnionSkinFade( player.m_onionSkinDistance)); - alpha = tcrop(tround(onionSkiFade * 255.0), 0, 255); - onionMode = (player.m_onionSkinDistance > 0) - ? Node::eOnionSkinFront - : ((player.m_onionSkinDistance < 0) ? Node::eOnionSkinBack - : Node::eOnionSkinNone); + alpha = tcrop(tround(onionSkiFade * 255.0), 0, 255); + + if (player.m_isShiftAndTraceEnabled && + !Preferences::instance()->areOnionColorsUsedForShiftAndTraceGhosts()) + onionMode = Node::eOnionSkinNone; + else { + onionMode = + (player.m_onionSkinDistance > 0) + ? Node::eOnionSkinFront + : ((player.m_onionSkinDistance < 0) ? Node::eOnionSkinBack + : Node::eOnionSkinNone); + } + } else if (player.m_opacity < 255) alpha = player.m_opacity; diff --git a/toonz/sources/toonzlib/tcenterlinevectorizerOld.cpp b/toonz/sources/toonzlib/tcenterlinevectorizerOld.cpp index 55640d1..25b66c4 100644 --- a/toonz/sources/toonzlib/tcenterlinevectorizerOld.cpp +++ b/toonz/sources/toonzlib/tcenterlinevectorizerOld.cpp @@ -818,7 +818,7 @@ TPointD CenterLineVectorizer::computeCenter(Node *na, Node *nb, double &r) { TPointD d = pa-pb; if(fabs(d.x)>fabs(d.y)) { - if(pa.x>pb.x) tswap(pa,pb); + if(pa.x>pb.x) std::swap(pa,pb); for(int x = pa.x; x<=pb.x; x++) { int y = pa.y + (pb.y-pa.y)*(x-pa.x)/(pb.x-pa.x); @@ -829,7 +829,7 @@ TPointD CenterLineVectorizer::computeCenter(Node *na, Node *nb, double &r) { } else { - if(pa.y>pb.y) tswap(pa,pb); + if(pa.y>pb.y) std::swap(pa,pb); for(int y = pa.y; y<=pb.y; y++) { int x = pa.x + (pb.x-pa.x)*(y-pa.y)/(pb.y-pa.y); @@ -863,8 +863,8 @@ Node *CenterLineVectorizer::findOtherSide(Node *node) { TPoint d1(tsign(dir.x), 0), d2(0, tsign(dir.y)); int num = abs(dir.y), den = abs(dir.x); if (num > den) { - tswap(d1, d2); - tswap(num, den); + std::swap(d1, d2); + std::swap(num, den); } TPoint pos = pix->m_pos; int i; @@ -1262,7 +1262,7 @@ void CenterLineVectorizer::traceLine(DataPixel *pix) { dpoints.push_back(point); } - tswap(naa, nbb); + std::swap(naa, nbb); } if (dpoints.size() == 0) naa->m_visited = nbb->m_visited = false; diff --git a/toonz/sources/toonzlib/tcleanupper.cpp b/toonz/sources/toonzlib/tcleanupper.cpp index ab10c53..f4cd7ac 100644 --- a/toonz/sources/toonzlib/tcleanupper.cpp +++ b/toonz/sources/toonzlib/tcleanupper.cpp @@ -835,7 +835,7 @@ TRasterImageP TCleanupper::autocenterOnly(const TRasterImageP &image, aff = aff.place(cxin, cyin, cpout, cqout); - if (rotate != 0 && rotate != 180) tswap(finalLx, finalLy); + if (rotate != 0 && rotate != 180) std::swap(finalLx, finalLy); TPointD pin = TPointD((rasterLx - 1) / 2.0, (rasterLy - 1) / 2.0); TPointD pout = TPointD((finalLx - 1) / 2.0, (finalLy - 1) / 2.0); diff --git a/toonz/sources/toonzlib/tcolumnfx.cpp b/toonz/sources/toonzlib/tcolumnfx.cpp index d26220d..4d39bf7 100644 --- a/toonz/sources/toonzlib/tcolumnfx.cpp +++ b/toonz/sources/toonzlib/tcolumnfx.cpp @@ -38,7 +38,6 @@ #include "toonz/levelset.h" #include "toonz/txshchildlevel.h" #include "toonz/fxdag.h" -#include "toonz/tcolumnfx.h" #include "toonz/tcolumnfxset.h" #include "toonz/stage.h" #include "toonz/fill.h" @@ -1159,6 +1158,12 @@ void TLevelColumnFx::doCompute(TTile &tile, double frame, ras = ti->getRaster(); if (sl->getProperties()->antialiasSoftness() > 0) { + // convert colormap raster to fullcolor raster before applying antialias + if (ti) { + TRaster32P convRas(ras->getSize()); + TRop::convert(convRas, ras, ti->getPalette(), TRect(), false, true); + ras = convRas; + } TRasterP appRas = ras->create(ras->getLx(), ras->getLy()); TRop::antialias(ras, appRas, 10, sl->getProperties()->antialiasSoftness()); @@ -1207,7 +1212,7 @@ void TLevelColumnFx::doCompute(TTile &tile, double frame, // Observe that inTile is in the standard reference, ie image's minus the // center coordinates - if (ti) { + if ((TRasterCM32P)ras) { // In the colormapped case, we have to convert the cmap to fullcolor TPalette *palette = ti->getPalette(); diff --git a/toonz/sources/toonzlib/tdistort.cpp b/toonz/sources/toonzlib/tdistort.cpp index 828d3b1..eabe26a 100644 --- a/toonz/sources/toonzlib/tdistort.cpp +++ b/toonz/sources/toonzlib/tdistort.cpp @@ -82,7 +82,7 @@ TPixelCM32 filterPixel(const TPointD &pos, const TRasterCM32P &rasIn) { else paintBlobs[paintBlobsSize++] = currBlob; for (; j > 0 && paintBlobs[j].tot > paintBlobs[j - 1].tot; j--) - tswap(paintBlobs[j], paintBlobs[j - 1]); + std::swap(paintBlobs[j], paintBlobs[j - 1]); // Same for ink blobs currBlob.val = P[i].getInk(); @@ -94,7 +94,7 @@ TPixelCM32 filterPixel(const TPointD &pos, const TRasterCM32P &rasIn) { else inkBlobs[inkBlobsSize++] = currBlob; for (; j > 0 && inkBlobs[j].tot > inkBlobs[j - 1].tot; j--) - tswap(inkBlobs[j], inkBlobs[j - 1]); + std::swap(inkBlobs[j], inkBlobs[j - 1]); } tone = troundp(tone_tot); diff --git a/toonz/sources/toonzlib/toonzscene.cpp b/toonz/sources/toonzlib/toonzscene.cpp index f3322b8..b0e43ac 100644 --- a/toonz/sources/toonzlib/toonzscene.cpp +++ b/toonz/sources/toonzlib/toonzscene.cpp @@ -1096,11 +1096,11 @@ TFilePath ToonzScene::getImportedLevelPath(const TFilePath path) const { if (ltype.m_ltype == UNKNOWN_XSHLEVEL) return path; const std::wstring &levelName = path.getWideName(); - const std::string &ext = path.getType(), &dots = path.getDots(); + const std::string &dots = path.getDots(); TFilePath importedLevelPath = getDefaultLevelPath(ltype.m_ltype, levelName).getParentDir() + - (levelName + ::to_wstring(dots + ext)); + path.getLevelNameW(); if (dots == "..") importedLevelPath = importedLevelPath.withFrame(TFrameId::EMPTY_FRAME); diff --git a/toonz/sources/toonzlib/toutlinevectorizer.cpp b/toonz/sources/toonzlib/toutlinevectorizer.cpp index b6aa75f..876f488 100644 --- a/toonz/sources/toonzlib/toutlinevectorizer.cpp +++ b/toonz/sources/toonzlib/toutlinevectorizer.cpp @@ -423,8 +423,8 @@ Node *OutlineVectorizer::findOtherSide(Node *node) { TPoint d1(tsign(dir.x), 0), d2(0, tsign(dir.y)); int num = abs(dir.y), den = abs(dir.x); if (num > den) { - tswap(d1, d2); - tswap(num, den); + std::swap(d1, d2); + std::swap(num, den); } TPoint pos = pix->m_pos; int i; diff --git a/toonz/sources/toonzlib/tpalettehandle.cpp b/toonz/sources/toonzlib/tpalettehandle.cpp index f1d5770..8937b21 100644 --- a/toonz/sources/toonzlib/tpalettehandle.cpp +++ b/toonz/sources/toonzlib/tpalettehandle.cpp @@ -144,12 +144,11 @@ void TPaletteHandle::setPalette(TPalette *palette, int styleIndex) { //----------------------------------------------------------------------------- void TPaletteHandle::setStyleIndex(int index) { - // if(m_styleIndex != index) - // { - m_styleIndex = index; - m_styleParamIndex = 0; - emit broadcastColorStyleSwitched(); - // } + if (m_styleIndex != index || m_styleParamIndex != 0) { + m_styleIndex = index; + m_styleParamIndex = 0; + emit broadcastColorStyleSwitched(); + } } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonzlib/trastercentroid.cpp b/toonz/sources/toonzlib/trastercentroid.cpp index 4f538ab..b667d6c 100644 --- a/toonz/sources/toonzlib/trastercentroid.cpp +++ b/toonz/sources/toonzlib/trastercentroid.cpp @@ -15,11 +15,6 @@ #include "tmsg.h" #include "copP.h"*/ -#if defined(MACOSX) || defined(LINUX) -#define TRUE 1 -#define FALSE 0 -#endif - /*------------------------------------------------------------------------*/ namespace { UCHAR First_preseed_table[256] = { @@ -187,7 +182,7 @@ int Displace_vector[8]; y_pos++; \ break; \ default: \ - assert(FALSE); \ + assert(false); \ } /*------------------------------------------------------------------------*/ @@ -232,7 +227,7 @@ static void initialize_displace_vector(void) { /*------------------------------------------------------------------------*/ -static int find_next_seed(const TRasterGR8P &r, int first_seed, UCHAR *&seed, +static int find_next_seed(const TRasterGR8P &r, bool first_seed, UCHAR *&seed, int &x_pos, int &y_pos) { static int Curr_x = 0, Curr_y = 0; UCHAR *pix; @@ -277,7 +272,7 @@ static void doComputeCentroid(const TRasterGR8P &r, TPoint &cp) { int x_num = 0, y_num = 0, den = 0; int x_pos, y_pos, old_x_pos, old_y_pos; int aux, old_displ = -1; - int first_seed; + bool first_seed; Lx = r->getLx(); Displace_vector[0] = -Lx - 1; @@ -289,10 +284,10 @@ static void doComputeCentroid(const TRasterGR8P &r, TPoint &cp) { Displace_vector[6] = Lx; Displace_vector[7] = Lx + 1; - first_seed = TRUE; + first_seed = true; while (find_next_seed(r, first_seed, seed, x_pos, y_pos)) { - first_seed = FALSE; + first_seed = false; *seed |= 0x2; diff --git a/toonz/sources/toonzlib/tstageobjecttree.cpp b/toonz/sources/toonzlib/tstageobjecttree.cpp index ae1d0d3..e0b02bd 100644 --- a/toonz/sources/toonzlib/tstageobjecttree.cpp +++ b/toonz/sources/toonzlib/tstageobjecttree.cpp @@ -328,7 +328,7 @@ bool checkId(TStageObjectTree *tree, const TStageObjectId &id) { void TStageObjectTree::swapColumns(int i, int j) { if (i == j) return; - if (i > j) tswap(i, j); + if (i > j) std::swap(i, j); std::map &pegbars = m_imp->m_pegbarTable; std::map::iterator iti, itj; std::map::const_iterator end = pegbars.end(); @@ -344,7 +344,7 @@ void TStageObjectTree::swapColumns(int i, int j) { } else if (iti != end && itj != end) { assert(iti->second); assert(itj->second); - tswap(iti->second, itj->second); + std::swap(iti->second, itj->second); iti->second->setId(iti->first); itj->second->setId(itj->first); } else if (iti == end) { diff --git a/toonz/sources/toonzlib/txshcolumn.cpp b/toonz/sources/toonzlib/txshcolumn.cpp index 8f29b2d..fb8d5ea 100644 --- a/toonz/sources/toonzlib/txshcolumn.cpp +++ b/toonz/sources/toonzlib/txshcolumn.cpp @@ -476,8 +476,8 @@ TXshColumn::ColumnType TXshColumn::toColumnType(int levelType) { //----------------------------------------------------------------------------- bool TXshColumn::isRendered() const { -// if (!getXsheet() || !getFx()) return false; -// if (!isPreviewVisible()) return false; + // if (!getXsheet() || !getFx()) return false; + // if (!isPreviewVisible()) return false; if (!getXsheet() || !isPreviewVisible()) return false; if (getColumnType() == eSoundType) return true; if (!getFx()) return false; @@ -650,4 +650,13 @@ QPair TXshColumn::getFilterInfo( if (!filterColors.contains(key)) return QPair(QObject::tr("None"), TPixel::Black); return filterColors.value(key); -} \ No newline at end of file +} + +//----------------------------------------------------------------------------- + +void TXshColumn::resetColumnProperties() { + setStatusWord(0); + setOpacity(255); + setColorTag(0); + setFilterColorId(FilterNone); +} diff --git a/toonz/sources/toonzlib/txshlevelcolumn.cpp b/toonz/sources/toonzlib/txshlevelcolumn.cpp index 47c012d..0e1efd8 100644 --- a/toonz/sources/toonzlib/txshlevelcolumn.cpp +++ b/toonz/sources/toonzlib/txshlevelcolumn.cpp @@ -91,6 +91,8 @@ TXshColumn *TXshLevelColumn::clone() const { column->setOpacity(getOpacity()); column->m_cells = m_cells; column->m_first = m_first; + column->setColorTag(getColorTag()); + column->setFilterColorId(getFilterColorId()); // column->updateIcon(); return column; diff --git a/toonz/sources/toonzlib/txshmeshcolumn.cpp b/toonz/sources/toonzlib/txshmeshcolumn.cpp index c9d6867..3af1bdc 100644 --- a/toonz/sources/toonzlib/txshmeshcolumn.cpp +++ b/toonz/sources/toonzlib/txshmeshcolumn.cpp @@ -59,8 +59,11 @@ TXshColumn *TXshMeshColumn::clone() const { TXshMeshColumn *column = new TXshMeshColumn(); column->setStatusWord(getStatusWord()); + column->setOpacity(getOpacity()); column->m_cells = m_cells; column->m_first = m_first; + column->setColorTag(getColorTag()); + column->setFilterColorId(getFilterColorId()); return column; } diff --git a/toonz/sources/toonzlib/txshpalettelevel.cpp b/toonz/sources/toonzlib/txshpalettelevel.cpp index 942720c..e24db02 100644 --- a/toonz/sources/toonzlib/txshpalettelevel.cpp +++ b/toonz/sources/toonzlib/txshpalettelevel.cpp @@ -77,12 +77,20 @@ void TXshPaletteLevel::load() { TFileStatus fs(path); TPersist *p = 0; TIStream is(path); + TPalette *palette = nullptr; if (is && fs.doesExist()) { - is >> p; - TPalette *palette = dynamic_cast(p); - palette->setPaletteName(path.getWideName()); - setPalette(palette); + std::string tagName; + if (is.matchTag(tagName) && tagName == "palette") { + std::string gname; + is.getTagParam("name", gname); + palette = new TPalette(); + palette->loadData(is); + palette->setGlobalName(::to_wstring(gname)); + is.matchEndTag(); + palette->setPaletteName(path.getWideName()); + setPalette(palette); + } } assert(m_palette); } diff --git a/toonz/sources/toonzlib/txshsimplelevel.cpp b/toonz/sources/toonzlib/txshsimplelevel.cpp index ee70807..b22ae35 100644 --- a/toonz/sources/toonzlib/txshsimplelevel.cpp +++ b/toonz/sources/toonzlib/txshsimplelevel.cpp @@ -1261,6 +1261,8 @@ void TXshSimpleLevel::load(const std::vector &fIds) { if (!loadingLevelRange.match(fIds[i])) continue; setFrame(fIds[i], TImageP()); } + const TImageInfo *info = lr->getImageInfo(fIds[0]); + if (info) set16BitChannelLevel(info->m_bitsPerSample == 16); } else { TLevelP level = lr->loadInfo(); for (TLevel::Iterator it = level->begin(); it != level->end(); it++) { @@ -1268,7 +1270,12 @@ void TXshSimpleLevel::load(const std::vector &fIds) { if (!loadingLevelRange.match(it->first)) continue; setFrame(it->first, TImageP()); } + const TImageInfo *info = lr->getImageInfo(level->begin()->first); + if (info) set16BitChannelLevel(info->m_bitsPerSample == 16); } + + if ((getType() & FULLCOLOR_TYPE) && !is16BitChannelLevel()) + setPalette(FullColorPalette::instance()->getPalette(getScene())); } setContentHistory(lr->getContentHistory() ? lr->getContentHistory()->clone() @@ -1384,7 +1391,10 @@ void TXshSimpleLevel::save(const TFilePath &fp, const TFilePath &oldFp, (!oldFp.isEmpty()) ? oldFp : getScene()->decodeFilePath(m_path); TFilePath dDstPath = getScene()->decodeFilePath(fp); - TSystem::touchParentDir(dDstPath); + if (!TSystem::touchParentDir(dDstPath)) + throw TSystemException( + dDstPath, + "The level cannot be saved: failed to access the target folder."); // backup if (Preferences::instance()->isLevelsBackupEnabled() && @@ -1960,26 +1970,24 @@ void TXshSimpleLevel::renumber(const std::vector &fids) { } ImageManager *im = ImageManager::instance(); - TImageCache *ic = TImageCache::instance(); + TImageCache *ic = TImageCache::instance(); std::map::iterator jt; { for (i = 0, jt = table.begin(); jt != table.end(); ++jt, ++i) { std::string Id = getImageId(jt->first); - ImageLoader::BuildExtData extData(this, jt->first); - TImageP img = im->getImage(Id, ImageManager::none, &extData); - ic->add(getIconId(jt->first), img, false); - im->rebind(Id, "^" + std::to_string(i)); - ic->remap("^icon:" + std::to_string(i), - getIconId(jt->first)); + ImageLoader::BuildExtData extData(this, jt->first); + TImageP img = im->getImage(Id, ImageManager::none, &extData); + ic->add(getIconId(jt->first), img, false); + im->rebind(Id, "^" + std::to_string(i)); + ic->remap("^icon:" + std::to_string(i), getIconId(jt->first)); } for (i = 0, jt = table.begin(); jt != table.end(); ++jt, ++i) { std::string Id = getImageId(jt->second); im->rebind("^" + std::to_string(i), Id); - ic->remap(getIconId(jt->second), - "^icon:" + std::to_string(i)); + ic->remap(getIconId(jt->second), "^icon:" + std::to_string(i)); im->renumber(Id, jt->second); } } @@ -2191,8 +2199,9 @@ TFilePath TXshSimpleLevel::getExistingHookFile( } assert(h >= 0); - return (h < 0) ? TFilePath() : decodedLevelPath.getParentDir() + - TFilePath(hookFiles[h].toStdWString()); + return (h < 0) ? TFilePath() + : decodedLevelPath.getParentDir() + + TFilePath(hookFiles[h].toStdWString()); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonzlib/xshhandlemanager.cpp b/toonz/sources/toonzlib/xshhandlemanager.cpp index 670f471..35111a9 100644 --- a/toonz/sources/toonzlib/xshhandlemanager.cpp +++ b/toonz/sources/toonzlib/xshhandlemanager.cpp @@ -7,7 +7,6 @@ #include "toonz/dpiscale.h" #include "toonz/txshsimplelevel.h" #include "toonz/stage.h" -#include "toonz/hook.h" #include "xshhandlemanager.h" diff --git a/toonz/sources/toonzqt/Resources/fxicons/Thumbs.db b/toonz/sources/toonzqt/Resources/fxicons/Thumbs.db deleted file mode 100644 index e8137dc..0000000 Binary files a/toonz/sources/toonzqt/Resources/fxicons/Thumbs.db and /dev/null differ diff --git a/toonz/sources/toonzqt/camerasettingswidget.cpp b/toonz/sources/toonzqt/camerasettingswidget.cpp index 5015006..7c77d08 100644 --- a/toonz/sources/toonzqt/camerasettingswidget.cpp +++ b/toonz/sources/toonzqt/camerasettingswidget.cpp @@ -32,7 +32,6 @@ // Qt includes #include #include -#include #include #include #include @@ -44,7 +43,6 @@ #include #include #include -#include using namespace std; using namespace DVGui; diff --git a/toonz/sources/toonzqt/colorfield.cpp b/toonz/sources/toonzqt/colorfield.cpp index 2d91a76..407aee8 100644 --- a/toonz/sources/toonzqt/colorfield.cpp +++ b/toonz/sources/toonzqt/colorfield.cpp @@ -203,6 +203,7 @@ ChannelField::ChannelField(QWidget *parent, const QString &string, int value, m_channelSlider->setRange(0, maxValue); m_channelSlider->setValue(value); + if (sliderWidth > 0) m_channelSlider->setFixedWidth(sliderWidth); //----layout QGridLayout *mainLayout = new QGridLayout(this); @@ -339,7 +340,7 @@ ColorField::ColorFieldEditorController *ColorField::m_editorController = 0; Return ColorField current color. */ ColorField::ColorField(QWidget *parent, bool isAlphaActive, TPixel32 color, - int squareSize, bool useStyleEditor) + int squareSize, bool useStyleEditor, int sliderWidth) : QWidget(parent) , m_color(color) , m_notifyEditingChange(true) @@ -355,16 +356,20 @@ ColorField::ColorField(QWidget *parent, bool isAlphaActive, TPixel32 color, m_colorSample = new StyleSample(this, squareSize, squareSize); m_colorSample->setColor(m_color); - m_redChannel = new ChannelField(this, tr("R:"), m_color.r); + m_redChannel = + new ChannelField(this, tr("R:"), m_color.r, 255, false, 13, sliderWidth); connect(m_redChannel, SIGNAL(valueChanged(int, bool)), SLOT(onRedChannelChanged(int, bool))); - m_greenChannel = new ChannelField(this, tr("G:"), m_color.g); + m_greenChannel = + new ChannelField(this, tr("G:"), m_color.g, 255, false, 13, sliderWidth); connect(m_greenChannel, SIGNAL(valueChanged(int, bool)), SLOT(onGreenChannelChanged(int, bool))); - m_blueChannel = new ChannelField(this, tr("B:"), m_color.b); + m_blueChannel = + new ChannelField(this, tr("B:"), m_color.b, 255, false, 13, sliderWidth); connect(m_blueChannel, SIGNAL(valueChanged(int, bool)), SLOT(onBlueChannelChanged(int, bool))); - m_alphaChannel = new ChannelField(this, tr("A:"), m_color.m); + m_alphaChannel = + new ChannelField(this, tr("A:"), m_color.m, 255, false, 13, sliderWidth); connect(m_alphaChannel, SIGNAL(valueChanged(int, bool)), SLOT(onAlphaChannelChanged(int, bool))); diff --git a/toonz/sources/toonzqt/functionpanel.cpp b/toonz/sources/toonzqt/functionpanel.cpp index 151d139..85535d5 100644 --- a/toonz/sources/toonzqt/functionpanel.cpp +++ b/toonz/sources/toonzqt/functionpanel.cpp @@ -197,7 +197,7 @@ void Ruler::compute() { // compute range double v0 = (m_x0 - m_pan) / m_unit; // left margin (world units) double v1 = (m_x1 - m_pan) / m_unit; // right margin (world units) - if (m_unit < 0) tswap(v0, v1); + if (m_unit < 0) std::swap(v0, v1); int i0 = tfloor((v0 - m_vOrigin) / m_step); // largest tick <=v0 is i0 * m_step int i1 = @@ -263,13 +263,11 @@ FunctionPanel::FunctionPanel(QWidget *parent, bool isFloating) if (m_isFloating) { // load the dialog size - TFilePath fp(ToonzFolder::getMyModuleDir() + TFilePath(mySettingsFileName)); - QSettings mySettings(toQString(fp), QSettings::IniFormat); + TFilePath fp(ToonzFolder::getMyModuleDir() + TFilePath("popups.ini")); + QSettings settings(toQString(fp), QSettings::IniFormat); - mySettings.beginGroup("Dialogs"); setGeometry( - mySettings.value("FunctionCurves", QRect(500, 500, 400, 300)).toRect()); - mySettings.endGroup(); + settings.value("FunctionCurves", QRect(500, 500, 400, 300)).toRect()); } } @@ -278,12 +276,10 @@ FunctionPanel::FunctionPanel(QWidget *parent, bool isFloating) FunctionPanel::~FunctionPanel() { if (m_isFloating) { // save the dialog size - TFilePath fp(ToonzFolder::getMyModuleDir() + TFilePath(mySettingsFileName)); - QSettings mySettings(toQString(fp), QSettings::IniFormat); + TFilePath fp(ToonzFolder::getMyModuleDir() + TFilePath("popups.ini")); + QSettings settings(toQString(fp), QSettings::IniFormat); - mySettings.beginGroup("Dialogs"); - mySettings.setValue("FunctionCurves", geometry()); - mySettings.endGroup(); + settings.setValue("FunctionCurves", geometry()); } delete m_dragTool; diff --git a/toonz/sources/toonzqt/functionsheet.cpp b/toonz/sources/toonzqt/functionsheet.cpp index caf0544..3b50a52 100644 --- a/toonz/sources/toonzqt/functionsheet.cpp +++ b/toonz/sources/toonzqt/functionsheet.cpp @@ -977,14 +977,11 @@ FunctionSheet::FunctionSheet(QWidget *parent, bool isFloating) if (m_isFloating) { // load the dialog size - TFilePath fp(ToonzFolder::getMyModuleDir() + TFilePath(mySettingsFileName)); - QSettings mySettings(toQString(fp), QSettings::IniFormat); - - mySettings.beginGroup("Dialogs"); - setGeometry( - mySettings.value("FunctionSpreadsheet", QRect(500, 500, 400, 300)) - .toRect()); - mySettings.endGroup(); + TFilePath fp(ToonzFolder::getMyModuleDir() + TFilePath("popups.ini")); + QSettings settings(toQString(fp), QSettings::IniFormat); + + setGeometry(settings.value("FunctionSpreadsheet", QRect(500, 500, 400, 300)) + .toRect()); } } @@ -992,12 +989,10 @@ FunctionSheet::FunctionSheet(QWidget *parent, bool isFloating) FunctionSheet::~FunctionSheet() { if (m_isFloating) { - TFilePath fp(ToonzFolder::getMyModuleDir() + TFilePath(mySettingsFileName)); - QSettings mySettings(toQString(fp), QSettings::IniFormat); + TFilePath fp(ToonzFolder::getMyModuleDir() + TFilePath("popups.ini")); + QSettings settings(toQString(fp), QSettings::IniFormat); - mySettings.beginGroup("Dialogs"); - mySettings.setValue("FunctionSpreadsheet", geometry()); - mySettings.endGroup(); + settings.setValue("FunctionSpreadsheet", geometry()); } } diff --git a/toonz/sources/toonzqt/functiontreeviewer.cpp b/toonz/sources/toonzqt/functiontreeviewer.cpp index 9fac83f..4fca61b 100644 --- a/toonz/sources/toonzqt/functiontreeviewer.cpp +++ b/toonz/sources/toonzqt/functiontreeviewer.cpp @@ -1519,7 +1519,7 @@ void FunctionTreeView::onDrag(TreeModel::Item *item, const QPoint &itemPos, QModelIndex i0 = channel->createIndex(), i1 = m_clickedItem->createIndex(); if (!i0.isValid() || !i1.isValid() || i0.parent() != i1.parent()) return; - if (i0.row() > i1.row()) tswap(i0, i1); + if (i0.row() > i1.row()) std::swap(i0, i1); FunctionTreeModel *md = static_cast(model()); diff --git a/toonz/sources/toonzqt/fxschematicnode.cpp b/toonz/sources/toonzqt/fxschematicnode.cpp index b83d8e0..8b21ec0 100644 --- a/toonz/sources/toonzqt/fxschematicnode.cpp +++ b/toonz/sources/toonzqt/fxschematicnode.cpp @@ -176,8 +176,13 @@ void FxColumnPainter::paint(QPainter *painter, SchematicViewer *viewer = sceneFx->getSchematicViewer(); viewer->getNodeColor(levelType, nodeColor); - painter->setBrush(nodeColor); - painter->setPen(Qt::NoPen); + if (m_isReference) { + painter->setBrush(viewer->getReferenceColumnColor()); + painter->setPen(nodeColor); + } else { + painter->setBrush(nodeColor); + painter->setPen(Qt::NoPen); + } painter->drawRect(0, 0, m_width, m_height); if (m_parent->isOpened() && m_parent->isNormalIconView()) { @@ -1373,7 +1378,7 @@ void FxSchematicPort::linkEffects(TFx *inputFx, TFx *fx, int inputId) { //----------------------------------------------------- -void FxSchematicPort::hideSnappedLinks() { +void FxSchematicPort::hideSnappedLinks(SchematicPort *) { if (!m_linkingTo) return; if (m_linkingTo->getType() == eFxInputPort && m_linkingTo->getLinkCount() == 1) { @@ -1405,7 +1410,7 @@ void FxSchematicPort::hideSnappedLinks() { //----------------------------------------------------- -void FxSchematicPort::showSnappedLinks() { +void FxSchematicPort::showSnappedLinks(SchematicPort *) { if (!m_linkingTo) return; if (m_linkingTo->getType() == eFxInputPort && m_linkingTo->getLinkCount() == 1) { @@ -1591,7 +1596,8 @@ void FxSchematicPort::contextMenuEvent(QGraphicsSceneContextMenuEvent *cme) { void FxSchematicPort::mouseMoveEvent(QGraphicsSceneMouseEvent *me) { SchematicPort::mouseMoveEvent(me); - if (m_ghostLink && !m_ghostLink->isVisible()) m_ghostLink->show(); + if (!m_ghostLinks.isEmpty() && !m_ghostLinks[0]->isVisible()) + m_ghostLinks[0]->show(); bool cntr = me->modifiers() == Qt::ControlModifier; if (m_currentTargetPort) { m_currentTargetPort->resetSnappedLinksOnDynamicPortFx(); @@ -1623,7 +1629,12 @@ void FxSchematicPort::mouseMoveEvent(QGraphicsSceneMouseEvent *me) { if (targetFx != m_ownerFx && cntr && getType() == eFxOutputPort) targetPort->handleSnappedLinksOnDynamicPortFx(groupedPorts, portId); else if (targetFx == m_ownerFx && getType() == eFxInputPort) { - if (m_ghostLink) m_ghostLink->hide(); + if (!m_ghostLinks.isEmpty()) { + for (SchematicLink *ghostLink : m_ghostLinks) + scene()->removeItem(ghostLink); + qDeleteAll(m_ghostLinks.begin(), m_ghostLinks.end()); + m_ghostLinks.clear(); + } FxSchematicNode *thisNode = dynamic_cast(getNode()); int thisId = thisNode->getInputDockId(getDock()); TFxPort *thisFxPort = targetFx->getInputPort(thisId); @@ -1873,15 +1884,18 @@ void FxSchematicNode::setSchematicNodePos(const QPointF &pos) const { TPointD p(pos.x(), pos.y()); if (!m_fx->getAttributes()->isGrouped() || m_fx->getAttributes()->isGroupEditing()) { + TPointD oldFxPos = m_fx->getAttributes()->getDagNodePos(); m_fx->getAttributes()->setDagNodePos(p); TMacroFx *macro = dynamic_cast(m_fx.getPointer()); if (macro) { - TPointD delta = p - macro->getRoot()->getAttributes()->getDagNodePos(); + TPointD delta = + p - (oldFxPos != TConst::nowhere ? oldFxPos : TPointD(0, 0)); std::vector fxs = macro->getFxs(); int i; for (i = 0; i < (int)fxs.size(); i++) { TPointD oldPos = fxs[i]->getAttributes()->getDagNodePos(); - fxs[i]->getAttributes()->setDagNodePos(oldPos + delta); + if (oldPos != TConst::nowhere) + fxs[i]->getAttributes()->setDagNodePos(oldPos + delta); } } } else { @@ -2941,6 +2955,9 @@ FxSchematicColumnNode::FxSchematicColumnNode(FxSchematicScene *scene, m_renderToggle->setIsActive(column->isPreviewVisible()); m_cameraStandToggle->setState( column->isCamstandVisible() ? (column->getOpacity() < 255 ? 2 : 1) : 0); + if (!column->isControl() && !column->isRendered() && + !column->getMeshColumn()) + m_columnPainter->setIsReference(); } // set geometry @@ -3099,6 +3116,7 @@ void FxSchematicColumnNode::onChangedSize(bool expand) { m_height = (m_isNormalIconView) ? 32 : 50; updateLinksGeometry(); update(); + emit nodeChangedSize(); } //----------------------------------------------------- @@ -3446,16 +3464,17 @@ void FxGroupNode::updateFxsDagPosition(const TPointD &pos) const { // placeNode() function. // if (m_groupedFxs[i]->getAttributes()->getDagNodePos() != TConst::nowhere) { - m_groupedFxs[i]->getAttributes()->setDagNodePos( - m_groupedFxs[i]->getAttributes()->getDagNodePos() + delta); + TPointD groupPos = m_groupedFxs[i]->getAttributes()->getDagNodePos(); + if (groupPos != TConst::nowhere) + m_groupedFxs[i]->getAttributes()->setDagNodePos(groupPos + delta); TMacroFx *macro = dynamic_cast(m_groupedFxs[i].getPointer()); if (macro) { std::vector fxs = macro->getFxs(); int i; for (i = 0; i < (int)fxs.size(); i++) { TPointD oldP = fxs[i]->getAttributes()->getDagNodePos(); - // if (oldP != TConst::nowhere) - fxs[i]->getAttributes()->setDagNodePos(oldP + delta); + if (oldP != TConst::nowhere) + fxs[i]->getAttributes()->setDagNodePos(oldP + delta); } } } diff --git a/toonz/sources/toonzqt/fxschematicscene.cpp b/toonz/sources/toonzqt/fxschematicscene.cpp index a79fd0a..e16c8ab 100644 --- a/toonz/sources/toonzqt/fxschematicscene.cpp +++ b/toonz/sources/toonzqt/fxschematicscene.cpp @@ -162,6 +162,8 @@ QList getRoots(const QList &fxs, TFxSet *terminals) { return roots; } +bool resizingNodes = false; +bool updatingScene = false; } // namespace //================================================================== @@ -353,6 +355,8 @@ void FxSchematicScene::setApplication(TApplication *app) { //------------------------------------------------------------------ void FxSchematicScene::updateScene() { + if (updatingScene) return; + updatingScene = true; if (!views().empty()) m_disconnectionLinks.clearAll(); m_connectionLinks.clearAll(); m_selectionOldPos.clear(); @@ -443,6 +447,23 @@ void FxSchematicScene::updateScene() { SchematicNode *node = addFxSchematicNode(fx); if (fx->getAttributes()->isGrouped()) editedGroup[fx->getAttributes()->getEditingGroupId()].append(node); + // If adding an unedited macro and nodes are not yet set, let's position the + // internal nodes now + if (macro) { + double minY = macro->getAttributes()->getDagNodePos().y; + double maxX = macro->getAttributes()->getDagNodePos().x; + double y = minY; + double x = maxX; + std::vector fxs = macro->getFxs(); + for (int j = 0; j < (int)fxs.size(); j++) { + TFx *macroFx = fxs[j].getPointer(); + if (macroFx && !m_placedFxs.contains(macroFx)) { + placeNodeAndParents(macroFx, x, maxX, minY); + y -= (m_gridDimension == eLarge ? 100 : 50); + minY = std::min(y, minY); + } + } + } } // grouped node @@ -460,6 +481,7 @@ void FxSchematicScene::updateScene() { updateEditedMacros(editedMacro); updateLink(); m_nodesToPlace.clear(); + updatingScene = false; } //------------------------------------------------------------------ @@ -528,6 +550,9 @@ FxSchematicNode *FxSchematicScene::addFxSchematicNode(TFx *fx) { connect(node, SIGNAL(fxNodeDoubleClicked()), this, SLOT(onFxNodeDoubleClicked())); + + connect(node, SIGNAL(nodeChangedSize()), this, SLOT(onNodeChangedSize())); + if (fx->getAttributes()->getDagNodePos() == TConst::nowhere) { node->resize(m_gridDimension == 0); placeNode(node); @@ -682,9 +707,44 @@ void FxSchematicScene::placeNode(FxSchematicNode *node) { node->getFx()->getAttributes()->setDagNodePos(TPointD(pos.x(), pos.y())); node->setPos(pos); return; - } else if (node->isA(eMacroFx) || node->isA(eNormalFx) || - node->isA(eNormalLayerBlendingFx) || node->isA(eNormalMatteFx) || - node->isA(eNormalImageAdjustFx)) { + } else if (node->isA(eMacroFx)) { + double minX = TConst::nowhere.x, minY = TConst::nowhere.y, maxY; + QPointF pos; + TMacroFx *macroFx = dynamic_cast(node->getFx()); + std::vector fxs = macroFx->getFxs(); + int k; + for (k = 0; k < (int)fxs.size(); k++) { + TFx *fx = fxs[k].getPointer(); + if (fx->getAttributes()->getDagNodePos() == TConst::nowhere) continue; + if (QPointF(minX, minY) == + QPointF(TConst::nowhere.x, TConst::nowhere.y)) { + minX = fx->getAttributes()->getDagNodePos().x; + minY = maxY = fx->getAttributes()->getDagNodePos().y; + continue; + } + minX = std::min(fx->getAttributes()->getDagNodePos().x, minX); + minY = std::min(fx->getAttributes()->getDagNodePos().y, minY); + maxY = std::max(fx->getAttributes()->getDagNodePos().y, maxY); + } + if (QPointF(minX, minY) == QPointF(TConst::nowhere.x, TConst::nowhere.y)) { + pos = sceneRect().center(); + nodeRect.moveTopLeft(pos); + while (!isAnEmptyZone(nodeRect)) nodeRect.translate(0, -step); + pos = nodeRect.topLeft(); + } else { + pos.setX(minX); + pos.setY((maxY + minY) / 2); + } + node->getFx()->getAttributes()->setDagNodePos(TPointD(pos.x(), pos.y())); + node->setPos(QPointF(pos)); + if (m_nodesToPlace.contains(node->getFx())) { + QList nodes = m_nodesToPlace[node->getFx()]; + int i; + for (i = 0; i < nodes.size(); i++) placeNode(nodes[i]); + } + return; + } else if (node->isA(eNormalFx) || node->isA(eNormalLayerBlendingFx) || + node->isA(eNormalMatteFx) || node->isA(eNormalImageAdjustFx)) { // I'm placing an effect or a macro TFx *inputFx = node->getFx()->getInputPort(0)->getFx(); QPointF pos; @@ -1118,6 +1178,40 @@ void FxSchematicScene::reorderScene() { TXsheet *xsh = m_xshHandle->getXsheet(); int i = 0; + + FxDag *fxDag = xsh->getFxDag(); + TFxSet *fxSet = fxDag->getInternalFxs(); + + // Let's reset every position to nowhere first + fxDag->getXsheetFx()->getAttributes()->setDagNodePos(TConst::nowhere); + + for (i = 0; i < fxDag->getOutputFxCount(); i++) { + TOutputFx *fx = fxDag->getOutputFx(i); + if (!fx) continue; + fx->getAttributes()->setDagNodePos(TConst::nowhere); + } + + for (i = 0; i < xsh->getColumnCount(); i++) { + TXshColumn *column = xsh->getColumn(i); + TFx *fx = column->getFx(); + if (!fx) continue; + fx->getAttributes()->setDagNodePos(TConst::nowhere); + } + + for (i = 0; i < fxSet->getFxCount(); i++) { + TFx *fx = fxSet->getFx(i); + fx->getAttributes()->setDagNodePos(TConst::nowhere); + TMacroFx *macro = dynamic_cast(fx); + if (macro && macro->isEditing()) { + std::vector fxs = macro->getFxs(); + int j; + for (j = 0; j < (int)fxs.size(); j++) { + fxs[j]->getAttributes()->setDagNodePos(TConst::nowhere); + } + } + } + + // Let's start placing them now for (i = 0; i < xsh->getColumnCount(); i++) { TXshColumn *column = xsh->getColumn(i); TFx *fx = column->getFx(); @@ -1160,15 +1254,16 @@ void FxSchematicScene::reorderScene() { double middleY = (sceneCenter.y() + minY + step) * 0.5; placeNodeAndParents(xsh->getFxDag()->getXsheetFx(), maxX, maxX, middleY); + y -= step; + minY = std::min(y, minY); - FxDag *fxDag = xsh->getFxDag(); - TFxSet *fxSet = fxDag->getInternalFxs(); for (i = 0; i < fxSet->getFxCount(); i++) { TFx *fx = fxSet->getFx(i); if (m_placedFxs.contains(fx)) continue; - fx->getAttributes()->setDagNodePos(TPointD(sceneCenter.x() + 120, minY)); - minY -= step; + placeNodeAndParents(fx, (sceneCenter.x() + 120), maxX, minY); + y -= step; + minY = std::min(y, minY); } updateScene(); } @@ -1182,7 +1277,8 @@ void FxSchematicScene::removeRetroLinks(TFx *fx, double &maxX) { if (!inFx) continue; TPointD inFxPos = inFx->getAttributes()->getDagNodePos(); TPointD fxPos = fx->getAttributes()->getDagNodePos(); - if (fxPos.x <= inFxPos.x) { + if (inFxPos != TConst::nowhere && fxPos != TConst::nowhere && + fxPos.x <= inFxPos.x) { while (fxPos.x <= inFxPos.x) fxPos.x += 150; maxX = std::max(fxPos.x + 150, maxX); fx->getAttributes()->setDagNodePos(fxPos); @@ -1214,8 +1310,23 @@ void FxSchematicScene::placeNodeAndParents(TFx *fx, double x, double &maxX, } } } - double y = minY; - fx->getAttributes()->setDagNodePos(TPointD(x, y)); + double y = minY; + TMacroFx *macro = dynamic_cast(fx); + if (macro) { + int tmpY = y; + std::vector fxs = macro->getFxs(); + for (int j = 0; j < (int)fxs.size(); j++) { + TFx *macroFx = fxs[j].getPointer(); + if (macroFx && !m_placedFxs.contains(macroFx)) { + placeNodeAndParents(macroFx, x, maxX, minY); + y -= step; + minY = std::min(y, minY); + } + } + tmpY = (minY + tmpY + step) * 0.5; + fx->getAttributes()->setDagNodePos(TPointD(x, tmpY)); + } else + fx->getAttributes()->setDagNodePos(TPointD(x, y)); if (fx->getOutputConnectionCount() == 0) minY -= step; x += 120; maxX = std::max(maxX, x); @@ -1499,6 +1610,7 @@ void FxSchematicScene::mousePressEvent(QGraphicsSceneMouseEvent *me) { FxsData fxsData; fxsData.setFxs(m_selection->getFxs(), m_selection->getLinks(), m_selection->getColumnIndexes(), m_xshHandle->getXsheet()); + // m_isConnected indicates that the all selected nodes are connected if (fxsData.isConnected() && me->button() == Qt::LeftButton && !port && !link) m_isConnected = true; } @@ -1613,9 +1725,19 @@ void FxSchematicScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *me) { bool FxSchematicScene::event(QEvent *e) { bool ret = SchematicScene::event(e); bool altPressed = QApplication::keyboardModifiers() == Qt::AltModifier; - if (m_linkUnlinkSimulation && m_altPressed != altPressed) - onAltModifierChanged(altPressed); - m_altPressed = altPressed; + if (m_altPressed != altPressed) { + // When Alt key is pressed, put the link lines on top of other items + // in order to enable to pick them up with itemAt() function. + double z = (altPressed) ? 5.0 : 0.0; + QList sceneItems = items(); + for (int i = 0; i < sceneItems.size(); i++) { + SchematicLink *link = dynamic_cast(sceneItems.at(i)); + if (link) link->setZValue(z); + } + + if (m_linkUnlinkSimulation) onAltModifierChanged(altPressed); + m_altPressed = altPressed; + } return ret; } @@ -1656,7 +1778,6 @@ void FxSchematicScene::onAltModifierChanged(bool altPressed) { if (m_disconnectionLinks.size() == 0 && m_linkUnlinkSimulation) simulateDisconnectSelection(altPressed); if (m_connectionLinks.size() == 0 && m_linkUnlinkSimulation) { - m_connectionLinks.showBridgeLinks(); #if QT_VERSION >= 0x050000 SchematicLink *link = dynamic_cast(itemAt(m_lastPos, QTransform())); @@ -1664,7 +1785,6 @@ void FxSchematicScene::onAltModifierChanged(bool altPressed) { SchematicLink *link = dynamic_cast(itemAt(m_lastPos)); #endif if (link && (!link->getEndPort() || !link->getStartPort())) return; - m_connectionLinks.hideBridgeLinks(); simulateInsertSelection(link, altPressed && !!link); } } else { @@ -1672,15 +1792,7 @@ void FxSchematicScene::onAltModifierChanged(bool altPressed) { simulateDisconnectSelection(altPressed); if (m_connectionLinks.size() > 0 && m_linkUnlinkSimulation) { m_connectionLinks.showBridgeLinks(); -#if QT_VERSION >= 0x050000 - SchematicLink *link = - dynamic_cast(itemAt(m_lastPos, QTransform())); -#else - SchematicLink *link = dynamic_cast(itemAt(m_lastPos)); -#endif - if (link && (!link->getEndPort() || !link->getStartPort())) return; - m_connectionLinks.hideBridgeLinks(); - simulateInsertSelection(link, altPressed && !!link); + simulateInsertSelection(0, false); } } } @@ -1751,62 +1863,60 @@ void FxSchematicScene::highlightLinks(FxSchematicNode *node, bool value) { //------------------------------------------------------------------ void FxSchematicScene::simulateDisconnectSelection(bool disconnect) { - if (m_selection->isEmpty()) return; - QList selectedFxs = m_selection->getFxs(); - if (selectedFxs.isEmpty()) return; - QMap visitedFxs; - int i; - for (i = 0; i < selectedFxs.size(); i++) - visitedFxs[selectedFxs[i].getPointer()] = false; - - TFx *inputFx = 0, *outputFx = 0; - findBoundariesFxs(inputFx, outputFx, visitedFxs); - FxSchematicNode *inputNode = m_table[inputFx]; - FxSchematicNode *outputNode = m_table[outputFx]; - assert(inputNode && outputNode); - - FxSchematicPort *inputPort = 0, *outputPort = 0; - SchematicPort *otherInputPort = 0; - QList otherOutputPorts; - if (inputNode->getInputPortCount() > 0) { - inputPort = inputNode->getInputPort(0); - if (inputPort) { - SchematicLink *inputLink = inputPort->getLink(0); - if (inputLink && !m_connectionLinks.isAnInputLink(inputLink)) { - if (!m_disconnectionLinks.isAnInputLink(inputLink)) - m_disconnectionLinks.addInputLink(inputLink); - otherInputPort = inputLink->getOtherPort(inputPort); + if (disconnect) { + if (m_selection->isEmpty()) return; + QList selectedFxs = m_selection->getFxs(); + if (selectedFxs.isEmpty()) return; + QMap visitedFxs; + int i; + for (i = 0; i < selectedFxs.size(); i++) + visitedFxs[selectedFxs[i].getPointer()] = false; + + TFx *inputFx = 0, *outputFx = 0; + findBoundariesFxs(inputFx, outputFx, visitedFxs); + FxSchematicNode *inputNode = m_table[inputFx]; + FxSchematicNode *outputNode = m_table[outputFx]; + assert(inputNode && outputNode); + + FxSchematicPort *inputPort = 0, *outputPort = 0; + SchematicPort *otherInputPort = 0; + QList otherOutputPorts; + if (inputNode->getInputPortCount() > 0) { + inputPort = inputNode->getInputPort(0); + if (inputPort) { + SchematicLink *inputLink = inputPort->getLink(0); + if (inputLink && !m_connectionLinks.isAnInputLink(inputLink)) { + if (!m_disconnectionLinks.isAnInputLink(inputLink)) + m_disconnectionLinks.addInputLink(inputLink); + otherInputPort = inputLink->getOtherPort(inputPort); + } } } - } - outputPort = outputNode->getOutputPort(); - if (outputPort) { - for (i = 0; i < outputPort->getLinkCount(); i++) { - SchematicLink *outputLink = outputPort->getLink(i); - if (outputLink && !m_connectionLinks.isAnOutputLink(outputLink)) { - if (!m_disconnectionLinks.isAnOutputLink(outputLink)) - m_disconnectionLinks.addOutputLink(outputLink); - otherOutputPorts.push_back(outputLink->getOtherPort(outputPort)); + outputPort = outputNode->getOutputPort(); + if (outputPort) { + for (i = 0; i < outputPort->getLinkCount(); i++) { + SchematicLink *outputLink = outputPort->getLink(i); + if (outputLink && !m_connectionLinks.isAnOutputLink(outputLink)) { + if (!m_disconnectionLinks.isAnOutputLink(outputLink)) + m_disconnectionLinks.addOutputLink(outputLink); + otherOutputPorts.push_back(outputLink->getOtherPort(outputPort)); + } } } - } - if (disconnect) { m_disconnectionLinks.hideInputLinks(); m_disconnectionLinks.hideOutputLinks(); + + if (otherInputPort) { + for (i = 0; i < otherOutputPorts.size(); i++) + m_disconnectionLinks.addBridgeLink( + otherOutputPorts[i]->makeLink(otherInputPort)); + } } else { m_disconnectionLinks.showInputLinks(); m_disconnectionLinks.showOutputLinks(); m_disconnectionLinks.removeInputLinks(); m_disconnectionLinks.removeOutputLinks(); - } - - if (otherInputPort) { - if (disconnect) { - for (i = 0; i < otherOutputPorts.size(); i++) - m_disconnectionLinks.addBridgeLink( - otherOutputPorts[i]->makeLink(otherInputPort)); - } else - m_disconnectionLinks.removeBridgeLinks(true); + m_disconnectionLinks.removeBridgeLinks(true); } } @@ -1814,7 +1924,7 @@ void FxSchematicScene::simulateDisconnectSelection(bool disconnect) { void FxSchematicScene::simulateInsertSelection(SchematicLink *link, bool connect) { - if (!link) { + if (!link || !connect) { m_connectionLinks.showBridgeLinks(); m_connectionLinks.hideInputLinks(); m_connectionLinks.hideOutputLinks(); @@ -1825,13 +1935,8 @@ void FxSchematicScene::simulateInsertSelection(SchematicLink *link, if (m_disconnectionLinks.isABridgeLink(link) || m_selection->isEmpty()) return; - if (connect) { - m_connectionLinks.addBridgeLink(link); - m_connectionLinks.hideBridgeLinks(); - } else { - m_connectionLinks.showBridgeLinks(); - m_connectionLinks.removeBridgeLinks(); - } + m_connectionLinks.addBridgeLink(link); + m_connectionLinks.hideBridgeLinks(); SchematicPort *inputPort = 0, *outputPort = 0; if (link) { @@ -1867,15 +1972,8 @@ void FxSchematicScene::simulateInsertSelection(SchematicLink *link, if (outputNodePort && inputPort) m_connectionLinks.addOutputLink(inputPort->makeLink(outputNodePort)); - if (connect) { - m_connectionLinks.showInputLinks(); - m_connectionLinks.showOutputLinks(); - } else { - m_connectionLinks.hideInputLinks(); - m_connectionLinks.hideOutputLinks(); - m_connectionLinks.removeInputLinks(true); - m_connectionLinks.removeOutputLinks(true); - } + m_connectionLinks.showInputLinks(); + m_connectionLinks.showOutputLinks(); } } //------------------------------------------------------------ @@ -1977,6 +2075,8 @@ void FxSchematicScene::closeInnerMacroEditor(int groupId) { //------------------------------------------------------------------ void FxSchematicScene::resizeNodes(bool maximizedNode) { + resizingNodes = true; + // resize nodes m_gridDimension = maximizedNode ? eLarge : eSmall; m_xshHandle->getXsheet()->getFxDag()->setDagGridDimension(m_gridDimension); @@ -2003,13 +2103,23 @@ void FxSchematicScene::resizeNodes(bool maximizedNode) { it3.value()->resizeNodes(maximizedNode); } updateScene(); + + resizingNodes = false; } //------------------------------------------------------------------ void FxSchematicScene::updatePositionOnResize(TFx *fx, bool maximizedNode) { TPointD oldPos = fx->getAttributes()->getDagNodePos(); + if (oldPos == TConst::nowhere) return; double oldPosY = oldPos.y - 25000; double newPosY = maximizedNode ? oldPosY * 2 : oldPosY * 0.5; fx->getAttributes()->setDagNodePos(TPointD(oldPos.x, newPosY + 25000)); } + +//------------------------------------------------------------------ + +void FxSchematicScene::onNodeChangedSize() { + if (resizingNodes) return; + updateScene(); +} diff --git a/toonz/sources/toonzqt/imageutils.cpp b/toonz/sources/toonzqt/imageutils.cpp index 91cb97b..4fb2c16 100644 --- a/toonz/sources/toonzqt/imageutils.cpp +++ b/toonz/sources/toonzqt/imageutils.cpp @@ -36,7 +36,6 @@ #include "tfiletype.h" #include "tfilepath.h" #include "ttoonzimage.h" -#include "trasterimage.h" #include "tvectorimage.h" #include "tstroke.h" @@ -90,7 +89,7 @@ void getFrameIds(TFrameId from, TFrameId to, const TLevelP &level, if (to.isEmptyFrame()) to = TFrameId((std::numeric_limits::max)()); - if (from > to) tswap(from, to); + if (from > to) std::swap(from, to); const TLevel::Table &table = *level->getTable(); diff --git a/toonz/sources/toonzqt/paletteviewergui.cpp b/toonz/sources/toonzqt/paletteviewergui.cpp index f85439e..2bb782a 100644 --- a/toonz/sources/toonzqt/paletteviewergui.cpp +++ b/toonz/sources/toonzqt/paletteviewergui.cpp @@ -138,16 +138,16 @@ PageViewer::PageViewer(QWidget *parent, PaletteViewType viewType, ViewMode defaultChipSize; switch (m_viewType) { case LEVEL_PALETTE: - defaultChipSize = (ViewMode)ChipSizeManager::instance()->chipSize_Palette; + defaultChipSize = LargeChips; break; case CLEANUP_PALETTE: - defaultChipSize = (ViewMode)ChipSizeManager::instance()->chipSize_Cleanup; + defaultChipSize = SmallChips; break; case STUDIO_PALETTE: - defaultChipSize = (ViewMode)ChipSizeManager::instance()->chipSize_Studio; + defaultChipSize = MediumChips; break; default: - defaultChipSize = (ViewMode)2; + defaultChipSize = LargeChips; break; } setViewMode(defaultChipSize); @@ -246,21 +246,6 @@ void PageViewer::setViewMode(ViewMode viewMode) { m_viewMode = viewMode; computeSize(); update(); - - // keep new view mode for reproducing the same mode when a new palette is made - switch (m_viewType) { - case LEVEL_PALETTE: - ChipSizeManager::instance()->chipSize_Palette = (int)m_viewMode; - break; - case CLEANUP_PALETTE: - ChipSizeManager::instance()->chipSize_Cleanup = (int)m_viewMode; - break; - case STUDIO_PALETTE: - ChipSizeManager::instance()->chipSize_Studio = (int)m_viewMode; - break; - default: - break; - } } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonzqt/paramfield.cpp b/toonz/sources/toonzqt/paramfield.cpp index 5c899ec..3c1f114 100644 --- a/toonz/sources/toonzqt/paramfield.cpp +++ b/toonz/sources/toonzqt/paramfield.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include using namespace DVGui; @@ -448,6 +450,38 @@ public: }; //----------------------------------------------------------------------------- +/*! FontParamFieldUndo +*/ +class FontParamFieldUndo final : public FxSettingsUndo { + TFontParamP m_param; + std::wstring m_oldValue, m_newValue; + +public: + FontParamFieldUndo(const TFontParamP param, QString name, TFxHandle *fxHandle) + : FxSettingsUndo(name, fxHandle), m_param(param) { + m_oldValue = param->getValue(); + m_newValue = m_oldValue; + } + + void onAdd() override { m_newValue = m_param->getValue(); } + + void undo() const override { + m_param->setValue(m_oldValue); + if (m_fxHandle) m_fxHandle->notifyFxChanged(); + } + + void redo() const override { + m_param->setValue(m_newValue); + if (m_fxHandle) m_fxHandle->notifyFxChanged(); + } + + QString getHistoryString() override { + QString str = QObject::tr("Modify Fx Param : %1").arg(m_name); + return str; + } +}; + +//----------------------------------------------------------------------------- /*! ToneCurveParamField Undo */ class ToneCurveParamFieldUndo final : public AnimatableFxSettingsUndo { @@ -1395,17 +1429,42 @@ void IntParamField::update(int frame) { // StringParamField //----------------------------------------------------------------------------- +namespace component { + +void MyTextEdit::keyPressEvent(QKeyEvent *event) { + QTextEdit::keyPressEvent(event); + if (event->key() == Qt::Key_Return) emit edited(); +} + +void MyTextEdit::focusOutEvent(QFocusEvent *event) { + QTextEdit::focusOutEvent(event); + emit edited(); +} +}; + StringParamField::StringParamField(QWidget *parent, QString name, const TStringParamP ¶m) : ParamField(parent, name, param) { QString str; m_paramName = str.fromStdString(param->getName()); - m_textFld = new LineEdit(name, this); - m_textFld->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - bool ret = - connect(m_textFld, SIGNAL(editingFinished()), this, SLOT(onChange())); - m_layout->addWidget(m_textFld); + bool ret = true; + if (param->isMultiLineEnabled()) { + m_multiTextFld = new component::MyTextEdit(name, this); + m_multiTextFld->setFixedHeight(80); + m_multiTextFld->setAcceptRichText(false); + m_multiTextFld->setStyleSheet( + "background:white;\ncolor:black;\nborder:1 solid black;"); + ret = ret && + connect(m_multiTextFld, SIGNAL(edited()), this, SLOT(onChange())); + m_layout->addWidget(m_multiTextFld); + } else { + m_textFld = new LineEdit(name, this); + m_textFld->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + ret = ret && + connect(m_textFld, SIGNAL(editingFinished()), this, SLOT(onChange())); + m_layout->addWidget(m_textFld); + } setLayout(m_layout); assert(ret); } @@ -1413,12 +1472,17 @@ StringParamField::StringParamField(QWidget *parent, QString name, //----------------------------------------------------------------------------- void StringParamField::onChange() { - std::wstring value = m_textFld->text().toStdWString(); - TUndo *undo = 0; + std::wstring value; + if (m_multiTextFld) + value = m_multiTextFld->toPlainText().toStdWString(); + else + value = m_textFld->text().toStdWString(); + TUndo *undo = 0; + + if (!m_actualParam || m_actualParam->getValue() == value) return; - TStringParamP stringParam = m_actualParam; - if (stringParam && stringParam->getValue() != value) - undo = new StringParamFieldUndo(stringParam, m_interfaceName, + if (m_actualParam->getValue() != value) + undo = new StringParamFieldUndo(m_actualParam, m_interfaceName, ParamField::m_fxHandleStat); m_actualParam->setValue(value); @@ -1447,13 +1511,147 @@ void StringParamField::update(int frame) { if (!m_actualParam || !m_currentParam) return; QString str; QString strValue = str.fromStdWString(m_actualParam->getValue()); - if (m_textFld->text() == strValue) return; - m_textFld->setText(strValue); - // Faccio in modo che il cursore sia sulla prima cifra, cosi' se la stringa - // da visualizzare e' piu' lunga del campo le cifre che vengono troncate sono - // le ultime e non le prime (dovrebbero essere quelle dopo la virgola). - m_textFld->setCursorPosition(0); + if (m_textFld) { + if (m_textFld->text() == strValue) return; + m_textFld->setText(strValue); + + // Faccio in modo che il cursore sia sulla prima cifra, cosi' se la stringa + // da visualizzare e' piu' lunga del campo le cifre che vengono troncate + // sono + // le ultime e non le prime (dovrebbero essere quelle dopo la virgola). + m_textFld->setCursorPosition(0); + } else { + if (m_multiTextFld->toPlainText() == strValue) return; + m_multiTextFld->setPlainText(strValue); + } +} + +//============================================================================= +// FontParamField +//----------------------------------------------------------------------------- + +FontParamField::FontParamField(QWidget *parent, QString name, + const TFontParamP ¶m) + : ParamField(parent, name, param) { + m_paramName = QString::fromStdString(param->getName()); + + m_fontCombo = new QFontComboBox(this); + m_styleCombo = new QComboBox(this); + m_sizeField = new IntField(this, false); + + m_sizeField->setRange(1, 500); + m_sizeField->enableSlider(false); + + m_layout->addWidget(m_fontCombo); + m_layout->addSpacing(5); + m_layout->addWidget(new QLabel(tr("Style:"), this), 0, + Qt::AlignRight | Qt::AlignVCenter); + m_layout->addWidget(m_styleCombo); + m_layout->addSpacing(5); + m_layout->addWidget(new QLabel(tr("Size:"), this), 0, + Qt::AlignRight | Qt::AlignVCenter); + m_layout->addWidget(m_sizeField); + + m_layout->addStretch(); + + setLayout(m_layout); + + bool ret = true; + ret = ret && connect(m_fontCombo, &QFontComboBox::currentFontChanged, this, + &FontParamField::findStyles); + ret = ret && connect(m_fontCombo, &QFontComboBox::currentFontChanged, this, + &FontParamField::onChange); + ret = ret && connect(m_styleCombo, SIGNAL(activated(const QString &)), this, + SLOT(onChange())); + ret = ret && connect(m_sizeField, SIGNAL(valueChanged(bool)), this, + SLOT(onSizeChange(bool))); + assert(ret); + + findStyles(m_fontCombo->currentFont()); +} + +//----------------------------------------------------------------------------- + +void FontParamField::findStyles(const QFont &font) { + QFontDatabase fontDatabase; + QString currentItem = m_styleCombo->currentText(); + m_styleCombo->clear(); + + QString style; + foreach (style, fontDatabase.styles(font.family())) + m_styleCombo->addItem(style); + + int styleIndex = m_styleCombo->findText(currentItem); + + if (styleIndex == -1) + m_styleCombo->setCurrentIndex(0); + else + m_styleCombo->setCurrentIndex(styleIndex); +} + +//----------------------------------------------------------------------------- + +void FontParamField::onSizeChange(bool isDragging) { + if (isDragging) return; + onChange(); +} + +//----------------------------------------------------------------------------- + +void FontParamField::onChange() { + QString family = m_fontCombo->currentFont().family(); + QString style = m_styleCombo->currentText(); + + int size = m_sizeField->getValue(); + int min, max; + m_sizeField->getRange(min, max); + if (size < min) size = min; + + QFontDatabase fontDatabase; + QFont font = fontDatabase.font(family, style, 10); + font.setPixelSize(size); + + TUndo *undo = 0; + + TFontParamP fontParam = m_actualParam; + QFont currentFont; + currentFont.fromString(QString::fromStdWString(fontParam->getValue())); + if (fontParam && currentFont != font) + undo = new FontParamFieldUndo(fontParam, m_interfaceName, + ParamField::m_fxHandleStat); + + m_actualParam->setValue(font.toString().toStdWString()); + emit currentParamChanged(); + m_currentParam->setValue(font.toString().toStdWString()); + emit actualParamChanged(); + + if (undo) TUndoManager::manager()->add(undo); +} + +//----------------------------------------------------------------------------- + +void FontParamField::setParam(const TParamP ¤t, const TParamP &actual, + int frame) { + m_currentParam = current; + m_actualParam = actual; + assert(m_currentParam); + assert(m_actualParam); + update(frame); +} + +//----------------------------------------------------------------------------- + +void FontParamField::update(int frame) { + if (!m_actualParam || !m_currentParam) return; + QFont font; + font.fromString(QString::fromStdWString(m_actualParam->getValue())); + + if (m_fontCombo->currentText() != font.family()) + m_fontCombo->setCurrentFont(font); + + m_styleCombo->setCurrentText(font.styleName()); + m_sizeField->setValue(font.pixelSize()); } //============================================================================= @@ -1660,6 +1858,8 @@ ParamField *ParamField::create(QWidget *parent, QString name, return new StringParamField(parent, name, stringParam); else if (TToneCurveParamP toneCurveParam = param) return new ToneCurveParamField(parent, name, toneCurveParam); + else if (TFontParamP fontParam = param) + return new FontParamField(parent, name, fontParam); else return 0; } diff --git a/toonz/sources/toonzqt/pluginhost.cpp b/toonz/sources/toonzqt/pluginhost.cpp index 895b130..38e327d 100644 --- a/toonz/sources/toonzqt/pluginhost.cpp +++ b/toonz/sources/toonzqt/pluginhost.cpp @@ -10,7 +10,6 @@ #else #include #endif -#include #include #include #include @@ -32,7 +31,6 @@ #include "plugin_param_view_interface.h" #include "plugin_ui_page_interface.h" #include "plugin_utilities.h" -#include "toonz_params.h" #include #include #include diff --git a/toonz/sources/toonzqt/schematicgroupeditor.cpp b/toonz/sources/toonzqt/schematicgroupeditor.cpp index dc39eae..d2f3fff 100644 --- a/toonz/sources/toonzqt/schematicgroupeditor.cpp +++ b/toonz/sources/toonzqt/schematicgroupeditor.cpp @@ -275,7 +275,9 @@ void FxSchematicGroupEditor::onNameChanged() { QRectF FxSchematicGroupEditor::boundingSceneRect() const { QRectF rect = m_groupedNode[0]->boundingRect(); - rect.moveTopLeft(m_groupedNode[0]->scenePos() - rect.topLeft()); + QPointF shiftPos(m_groupedNode[0]->scenePos().x() - rect.left(), + m_groupedNode[0]->scenePos().y() + rect.top() + 10); + rect.moveTopLeft(shiftPos); int i; for (i = 0; i < m_groupedNode.size(); i++) { FxSchematicNode *node = dynamic_cast(m_groupedNode[i]); @@ -283,7 +285,9 @@ QRectF FxSchematicGroupEditor::boundingSceneRect() const { TFx *fx = node->getFx(); assert(fx); QRectF app = node->boundingRect(); - app.moveTopLeft(node->scenePos() - app.topLeft()); + QPointF shiftAppPos(node->scenePos().x() - app.left(), + node->scenePos().y() + app.top() + 10); + app.moveTopLeft(shiftAppPos); bool isASubgroupedNode = fx->getAttributes()->getEditingGroupId() != m_groupId; if (isASubgroupedNode) { @@ -370,7 +374,9 @@ void FxSchematicMacroEditor::onNameChanged() { QRectF FxSchematicMacroEditor::boundingSceneRect() const { QRectF rect = m_groupedNode[0]->boundingRect(); - rect.moveTopLeft(m_groupedNode[0]->scenePos() - rect.topLeft()); + QPointF shiftPos(m_groupedNode[0]->scenePos().x() - rect.left(), + m_groupedNode[0]->scenePos().y() + rect.top() + 10); + rect.moveTopLeft(shiftPos); int i; for (i = 0; i < m_groupedNode.size(); i++) { FxSchematicNode *node = dynamic_cast(m_groupedNode[i]); @@ -378,7 +384,9 @@ QRectF FxSchematicMacroEditor::boundingSceneRect() const { TFx *fx = node->getFx(); assert(fx); QRectF app = node->boundingRect(); - app.moveTopLeft(node->scenePos() - app.topLeft()); + QPointF shiftAppPos(node->scenePos().x() - app.left(), + node->scenePos().y() + app.top() + 10); + app.moveTopLeft(shiftAppPos); #if QT_VERSION >= 0x050000 rect = rect.united(app); #else @@ -403,11 +411,14 @@ void FxSchematicMacroEditor::setGroupedNodeZValue(int zValue) { //--------------------------------------------------------------- void FxSchematicMacroEditor::mouseMoveEvent(QGraphicsSceneMouseEvent *e) { + QPointF prevPos = pos(); SchematicWindowEditor::mouseMoveEvent(e); if (m_button == Qt::LeftButton) { - TFx *root = m_macro->getRoot(); - TPointD pos = root->getAttributes()->getDagNodePos(); - m_macro->getAttributes()->setDagNodePos(pos); + QPointF delta = pos() - prevPos; + TFx *root = m_macro->getRoot(); + TPointD oldPos = m_macro->getAttributes()->getDagNodePos(); + m_macro->getAttributes()->setDagNodePos(oldPos + + TPointD(delta.x(), delta.y())); } } @@ -440,7 +451,9 @@ StageSchematicGroupEditor::~StageSchematicGroupEditor() {} QRectF StageSchematicGroupEditor::boundingSceneRect() const { QRectF rect = m_groupedNode[0]->boundingRect(); - rect.moveTopLeft(m_groupedNode[0]->scenePos() - rect.topLeft()); + QPointF shiftPos(m_groupedNode[0]->scenePos().x() - rect.left(), + m_groupedNode[0]->scenePos().y() + rect.top() + 10); + rect.moveTopLeft(shiftPos); int i; for (i = 0; i < m_groupedNode.size(); i++) { StageSchematicNode *node = @@ -449,7 +462,9 @@ QRectF StageSchematicGroupEditor::boundingSceneRect() const { TStageObject *obj = node->getStageObject(); assert(obj); QRectF app = node->boundingRect(); - app.moveTopLeft(node->scenePos() - app.topLeft()); + QPointF shiftAppPos(node->scenePos().x() - app.left(), + node->scenePos().y() + app.top() + 10); + app.moveTopLeft(shiftAppPos); bool isASubgroupedNode = obj->getEditingGroupId() != m_groupId; if (isASubgroupedNode) app.adjust(-30, -30, 30, 30); #if QT_VERSION >= 0x050000 diff --git a/toonz/sources/toonzqt/schematicnode.cpp b/toonz/sources/toonzqt/schematicnode.cpp index 7daf2b6..b53c62f 100644 --- a/toonz/sources/toonzqt/schematicnode.cpp +++ b/toonz/sources/toonzqt/schematicnode.cpp @@ -260,7 +260,12 @@ void SchematicToggle::paint(QPainter *painter, sourceRect.height() * getDevPixRatio()); painter->drawPixmap(rect, redPm, newRect); } else if (!m_imageOff.isNull()) { - painter->fillRect(boundingRect().toRect(), m_colorOff); + QPen pen(m_colorOn); + pen.setWidthF(0.5); + painter->setPen(pen); + painter->setBrush(m_colorOff); + double d = pen.widthF() / 2.0; + painter->drawRect(boundingRect().adjusted(d, d, -d, -d)); QRect sourceRect = scene()->views()[0]->matrix().mapRect(QRect(0, 0, 18, 17)); QPixmap redPm = m_imageOff.pixmap(sourceRect.size()); @@ -527,6 +532,12 @@ void SchematicLink::updatePath(SchematicPort *startPort, //-------------------------------------------------------- +void SchematicLink::updateEndPos(const QPointF &endPos) { + if (m_startPort) updatePath(m_startPort->getLinkEndPoint(), endPos); +} + +//-------------------------------------------------------- + SchematicPort *SchematicLink::getOtherPort(const SchematicPort *port) const { if (port == m_startPort) return m_endPort; @@ -624,7 +635,6 @@ SchematicPort::SchematicPort(QGraphicsItem *parent, SchematicNode *node, , m_node(node) , m_buttonState(Qt::NoButton) , m_highlighted(false) - , m_ghostLink(0) , m_linkingTo(0) , m_hook(0, 0) , m_type(type) { @@ -645,27 +655,28 @@ SchematicPort::~SchematicPort() { m_links.clear(); } void SchematicPort::mouseMoveEvent(QGraphicsSceneMouseEvent *me) { if (m_buttonState != Qt::LeftButton) return; - if (!m_ghostLink) return; + if (m_ghostLinks.isEmpty()) return; - if (m_linkingTo) { - showSnappedLinks(); - m_linkingTo = 0; - } // Snapping SchematicPort *linkingTo = searchPort(me->scenePos()); if (!linkingTo) { + for (SchematicLink *ghostLink : m_ghostLinks) { + ghostLink->updateEndPos(me->scenePos()); + ghostLink->getStartPort()->showSnappedLinks(m_linkingTo); + } if (m_linkingTo) { m_linkingTo->highLight(false); m_linkingTo->update(); + m_linkingTo = nullptr; } - m_ghostLink->updatePath(this->getLinkEndPoint(), me->scenePos()); - m_linkingTo = linkingTo; } // if to be connected something else if (linkingTo != this) { - m_ghostLink->updatePath(this, linkingTo); m_linkingTo = linkingTo; - hideSnappedLinks(); + for (SchematicLink *ghostLink : m_ghostLinks) { + ghostLink->updatePath(ghostLink->getStartPort(), linkingTo); + ghostLink->getStartPort()->hideSnappedLinks(m_linkingTo); + } } // autopan QGraphicsView *viewer = scene()->views()[0]; @@ -697,9 +708,32 @@ void SchematicPort::mousePressEvent(QGraphicsSceneMouseEvent *me) { m_buttonState = Qt::LeftButton; QPointF endPos(me->pos()); - m_ghostLink = new SchematicLink(0, scene()); - m_ghostLink->setZValue(3.0); - m_ghostLink->updatePath(this->getLinkEndPoint(), me->scenePos()); + // Enable to connect multiple links from all selected nodes + // only when ( Ctrl + ) dragging from the eStageParentPort. + if (getType() == 101) { // eStageParentPort + QList items = scene()->selectedItems(); + if (items.empty()) return; + for (auto const &item : items) { + SchematicNode *node = dynamic_cast(item); + if (node) { + SchematicPort *parentPort = + node->getPort(0); // id 0 is for parent port. + if (parentPort) { + SchematicLink *ghostLink = new SchematicLink(0, scene()); + ghostLink->setStartPort(parentPort); + ghostLink->setZValue(3.0); + ghostLink->updateEndPos(me->scenePos()); + m_ghostLinks.push_back(ghostLink); + } + } + } + } else { + SchematicLink *ghostLink = new SchematicLink(0, scene()); + ghostLink->setStartPort(this); + ghostLink->setZValue(3.0); + ghostLink->updateEndPos(me->scenePos()); + m_ghostLinks.push_back(ghostLink); + } emit(isClicked()); } } @@ -710,22 +744,39 @@ void SchematicPort::mouseReleaseEvent(QGraphicsSceneMouseEvent *me) { if (me->modifiers() != Qt::ControlModifier && me->button() != Qt::RightButton) QGraphicsItem::mouseReleaseEvent(me); - if (m_ghostLink) m_ghostLink->hide(); - if (m_buttonState == Qt::LeftButton) emit(isReleased(me->scenePos())); // The link is added to the scene only if the user released the left mouse // button over // a SchematicPort different from SchematicPort of the parent node. - if (m_buttonState == Qt::LeftButton && m_linkingTo && - !isLinkedTo(m_linkingTo) && linkTo(m_linkingTo, true)) { - linkTo(m_linkingTo); + bool somethingChanged = false; + if (m_buttonState == Qt::LeftButton && m_linkingTo) { + TUndoManager::manager()->beginBlock(); + for (SchematicLink *ghostLink : m_ghostLinks) { + SchematicPort *port = ghostLink->getStartPort(); + if (!port) continue; + if (!port->isLinkedTo(m_linkingTo) && port->linkTo(m_linkingTo, true)) { + port->linkTo(m_linkingTo); + somethingChanged = true; + } else + port->showSnappedLinks(m_linkingTo); + } m_buttonState = Qt::NoButton; m_linkingTo = 0; + TUndoManager::manager()->endBlock(); + } + + if (!m_ghostLinks.isEmpty()) { + for (SchematicLink *ghostLink : m_ghostLinks) + scene()->removeItem(ghostLink); + qDeleteAll(m_ghostLinks.begin(), m_ghostLinks.end()); + m_ghostLinks.clear(); + } + + if (somethingChanged) { emit sceneChanged(); emit xsheetChanged(); - } else - showSnappedLinks(); + } } //-------------------------------------------------------- diff --git a/toonz/sources/toonzqt/schematicviewer.cpp b/toonz/sources/toonzqt/schematicviewer.cpp index 904fda4..b683264 100644 --- a/toonz/sources/toonzqt/schematicviewer.cpp +++ b/toonz/sources/toonzqt/schematicviewer.cpp @@ -403,10 +403,6 @@ void SchematicSceneViewer::zoomQt(bool zoomin, bool resetZoom) { #else double scale2 = matrix().det(); #endif - - // if the zoom scale is changed over 100% in FxSchematic, call updateScene - bool beforeIsLarge = (scale2 >= 1.0); - if (resetZoom || ((scale2 < 100000 || !zoomin) && (scale2 > 0.001 * 0.05 || zoomin))) { double oldZoomScale = sqrt(scale2); @@ -421,16 +417,6 @@ void SchematicSceneViewer::zoomQt(bool zoomin, bool resetZoom) { mapToScene(QRect(rect.center(), QSize(2, 2))).boundingRect()); setMatrix(scale, true); centerOn(sceneCenterRect.center()); - -#if QT_VERSION >= 0x050000 - bool afterIsLarge = (matrix().determinant() >= 1.0); -#else - bool afterIsLarge = (matrix().det() >= 1.0); -#endif - if (beforeIsLarge != afterIsLarge) { - FxSchematicScene *fxScene = qobject_cast(scene()); - if (fxScene) fxScene->updateScene(); - } } } @@ -440,51 +426,20 @@ void SchematicSceneViewer::zoomQt(bool zoomin, bool resetZoom) { */ void SchematicSceneViewer::changeScale(const QPoint &winPos, qreal scaleFactor) { -#if QT_VERSION >= 0x050000 - bool beforeIsLarge = (matrix().determinant() >= 1.0); -#else - bool beforeIsLarge = (matrix().det() >= 1.0); -#endif QPointF startScenePos = mapToScene(winPos); QMatrix scale = QMatrix().scale(scaleFactor, scaleFactor); setMatrix(scale, true); QPointF endScenePos = mapToScene(winPos); QPointF delta = endScenePos - startScenePos; translate(delta.x(), delta.y()); - -#if QT_VERSION >= 0x050000 - bool afterIsLarge = (matrix().determinant() >= 1.0); -#else - bool afterIsLarge = (matrix().det() >= 1.0); -#endif - if (beforeIsLarge != afterIsLarge) { - FxSchematicScene *fxScene = qobject_cast(scene()); - if (fxScene) fxScene->updateScene(); - } } //------------------------------------------------------------------ void SchematicSceneViewer::fitScene() { if (scene()) { -#if QT_VERSION >= 0x050000 - bool beforeIsLarge = (matrix().determinant() >= 1.0); -#else - bool beforeIsLarge = (matrix().det() >= 1.0); -#endif - QRectF rect = scene()->itemsBoundingRect(); fitInView(rect, Qt::KeepAspectRatio); - -#if QT_VERSION >= 0x050000 - bool afterIsLarge = (matrix().determinant() >= 1.0); -#else - bool afterIsLarge = (matrix().det() >= 1.0); -#endif - if (beforeIsLarge != afterIsLarge) { - FxSchematicScene *fxScene = qobject_cast(scene()); - if (fxScene) fxScene->updateScene(); - } } } @@ -506,11 +461,6 @@ void SchematicSceneViewer::reorderScene() { //------------------------------------------------------------------ void SchematicSceneViewer::normalizeScene() { -#if QT_VERSION >= 0x050000 - bool beforeIsLarge = (matrix().determinant() >= 1.0); -#else - bool beforeIsLarge = (matrix().det() >= 1.0); -#endif // See QGraphicsView::mapToScene()'s doc for details QRect rect(0, 0, width(), height()); QRectF sceneCenterRect( @@ -520,16 +470,6 @@ void SchematicSceneViewer::normalizeScene() { scale(1.32, 1.32); #endif centerOn(sceneCenterRect.center()); - -#if QT_VERSION >= 0x050000 - bool afterIsLarge = (matrix().determinant() >= 1.0); -#else - bool afterIsLarge = (matrix().det() >= 1.0); -#endif - if (beforeIsLarge != afterIsLarge) { - FxSchematicScene *fxScene = qobject_cast(scene()); - if (fxScene) fxScene->updateScene(); - } } //------------------------------------------------------------------ diff --git a/toonz/sources/toonzqt/stageobjectselection.cpp b/toonz/sources/toonzqt/stageobjectselection.cpp index dff2bed..bceff3a 100644 --- a/toonz/sources/toonzqt/stageobjectselection.cpp +++ b/toonz/sources/toonzqt/stageobjectselection.cpp @@ -54,6 +54,7 @@ public: TXshColumnP column = xsh->getColumn(it->getIndex()); assert(column); TFx *columnFx = column->getFx(); + if (!columnFx) continue; int i; for (i = 0; i < columnFx->getOutputConnectionCount(); i++) m_columnFxConnections[*it].append(columnFx->getOutputConnection(i)); diff --git a/toonz/sources/toonzqt/stageschematicnode.cpp b/toonz/sources/toonzqt/stageschematicnode.cpp index 4b57ebe..966543c 100644 --- a/toonz/sources/toonzqt/stageschematicnode.cpp +++ b/toonz/sources/toonzqt/stageschematicnode.cpp @@ -26,7 +26,6 @@ #include "toonz/txshchildlevel.h" #include "toonz/txshlevelcolumn.h" #include "toonz/txshleveltypes.h" -#include "toonz/txshleveltypes.h" #include "toonz/tcolumnhandle.h" #include "toonz/hook.h" #include "toonz/preferences.h" @@ -139,8 +138,14 @@ void ColumnPainter::paint(QPainter *painter, SchematicViewer *viewer = stageScene->getSchematicViewer(); viewer->getNodeColor(levelType, nodeColor); - painter->setBrush(nodeColor); - painter->setPen(Qt::NoPen); + if (m_isReference && levelType != PLT_XSHLEVEL) { + painter->setBrush(viewer->getReferenceColumnColor()); + painter->setPen(nodeColor); + } else { + painter->setBrush(nodeColor); + painter->setPen(Qt::NoPen); + } + if (levelType == PLT_XSHLEVEL) painter->drawRoundRect(0, 0, m_width, m_height, 32, 99); else @@ -836,33 +841,33 @@ SchematicPort *StageSchematicNodePort::searchPort(const QPointF &scenePos) { //-------------------------------------------------------- -void StageSchematicNodePort::hideSnappedLinks() { - if (!m_linkingTo) return; +void StageSchematicNodePort::hideSnappedLinks(SchematicPort *linkingPort) { + if (!linkingPort) return; if (getType() == eStageChildPort && - m_linkingTo->getType() == eStageParentPort && - m_linkingTo->getLinkCount() == 1) - m_linkingTo->getLink(0)->hide(); + linkingPort->getType() == eStageParentPort && + linkingPort->getLinkCount() == 1) + linkingPort->getLink(0)->hide(); if (getType() == eStageParentPort && - m_linkingTo->getType() == eStageChildPort && getLinkCount() == 1) + linkingPort->getType() == eStageChildPort && getLinkCount() == 1) getLink(0)->hide(); } //-------------------------------------------------------- -void StageSchematicNodePort::showSnappedLinks() { - if (!m_linkingTo) return; +void StageSchematicNodePort::showSnappedLinks(SchematicPort *linkingPort) { + if (!linkingPort) return; if (getType() == eStageChildPort && - m_linkingTo->getType() == eStageParentPort && - m_linkingTo->getLinkCount() == 1) { - m_linkingTo->getLink(0)->show(); - m_linkingTo->highLight(true); - m_linkingTo->update(); + linkingPort->getType() == eStageParentPort && + linkingPort->getLinkCount() == 1) { + linkingPort->getLink(0)->show(); + linkingPort->highLight(true); + linkingPort->update(); } if (getType() == eStageParentPort && - m_linkingTo->getType() == eStageChildPort && getLinkCount() == 1) { + linkingPort->getType() == eStageChildPort && getLinkCount() == 1) { getLink(0)->show(); - m_linkingTo->highLight(true); - m_linkingTo->update(); + linkingPort->highLight(true); + linkingPort->update(); } } @@ -970,7 +975,7 @@ SchematicPort *StageSchematicSplinePort::searchPort(const QPointF &scenePos) { //-------------------------------------------------------- -void StageSchematicSplinePort::hideSnappedLinks() { +void StageSchematicSplinePort::hideSnappedLinks(SchematicPort *) { if (!m_linkingTo) return; StageSchematicNode *node = dynamic_cast(getNode()); StageSchematicSplineNode *splineNode = @@ -982,7 +987,7 @@ void StageSchematicSplinePort::hideSnappedLinks() { //-------------------------------------------------------- -void StageSchematicSplinePort::showSnappedLinks() { +void StageSchematicSplinePort::showSnappedLinks(SchematicPort *) { if (!m_linkingTo) return; StageSchematicNode *node = dynamic_cast(getNode()); StageSchematicSplineNode *splineNode = @@ -1744,6 +1749,10 @@ StageSchematicColumnNode::StageSchematicColumnNode(StageSchematicScene *scene, m_columnPainter = new ColumnPainter(this, m_width, m_height, m_name); m_columnPainter->setZValue(1); + if (column && !column->isControl() && !column->isRendered() && + !column->getMeshColumn()) + m_columnPainter->setIsReference(); + int levelType; QString levelName; getLevelTypeAndName(levelType, levelName); @@ -1883,6 +1892,7 @@ void StageSchematicColumnNode::onChangedSize(bool expand) { updatePortsPosition(); updateLinksGeometry(); update(); + emit nodeChangedSize(); } //-------------------------------------------------------- diff --git a/toonz/sources/toonzqt/stageschematicscene.cpp b/toonz/sources/toonzqt/stageschematicscene.cpp index f84b657..8718f81 100644 --- a/toonz/sources/toonzqt/stageschematicscene.cpp +++ b/toonz/sources/toonzqt/stageschematicscene.cpp @@ -106,6 +106,8 @@ void keepSubgroup(QMap> &editedGroup) { } } +bool resizingNodes = false; +bool updatingScene = false; } // namespace //================================================================== @@ -194,6 +196,8 @@ void StageSchematicScene::onSelectionSwitched(TSelection *oldSel, //------------------------------------------------------------------ void StageSchematicScene::updateScene() { + if (updatingScene) return; + updatingScene = true; clearAllItems(); QPointF firstPos = sceneRect().center(); @@ -351,6 +355,7 @@ void StageSchematicScene::updateScene() { } } m_nodesToPlace.clear(); + updatingScene = false; } //------------------------------------------------------------------ @@ -367,6 +372,7 @@ StageSchematicNode *StageSchematicScene::addStageSchematicNode( connect(node, SIGNAL(currentColumnChanged(int)), this, SLOT(onCurrentColumnChanged(int))); connect(node, SIGNAL(editObject()), this, SIGNAL(editObject())); + connect(node, SIGNAL(nodeChangedSize()), this, SLOT(onNodeChangedSize())); // specify the node position if (pegbar->getDagNodePos() == TConst::nowhere) { @@ -539,6 +545,7 @@ void StageSchematicScene::updateNestedGroupEditors(StageSchematicNode *node, //------------------------------------------------------------------ void StageSchematicScene::resizeNodes(bool maximizedNode) { + resizingNodes = true; m_gridDimension = maximizedNode ? eLarge : eSmall; TStageObjectTree *pegTree = m_xshHandle->getXsheet()->getStageObjectTree(); pegTree->setDagGridDimension(m_gridDimension); @@ -578,6 +585,7 @@ void StageSchematicScene::resizeNodes(bool maximizedNode) { for (it2 = m_groupEditorTable.begin(); it2 != m_groupEditorTable.end(); it2++) it2.value()->resizeNodes(maximizedNode); updateScene(); + resizingNodes = false; } //------------------------------------------------------------------ @@ -585,6 +593,7 @@ void StageSchematicScene::resizeNodes(bool maximizedNode) { void StageSchematicScene::updatePositionOnResize(TStageObject *obj, bool maximizedNode) { TPointD oldPos = obj->getDagNodePos(); + if (oldPos == TConst::nowhere) return; double oldPosY = oldPos.y - 25500; double newPosY = maximizedNode ? oldPosY * 2 : oldPosY * 0.5; obj->setDagNodePos(TPointD(oldPos.x, newPosY + 25500)); @@ -595,6 +604,7 @@ void StageSchematicScene::updatePositionOnResize(TStageObject *obj, void StageSchematicScene::updateSplinePositionOnResize(TStageObjectSpline *spl, bool maximizedNode) { TPointD oldPos = spl->getDagNodePos(); + if (oldPos == TConst::nowhere) return; double oldPosY = oldPos.y - 25500; double newPosY = maximizedNode ? oldPosY * 2 : oldPosY * 0.5; spl->setDagNodePos(TPointD(oldPos.x, newPosY + 25500)); @@ -1249,3 +1259,10 @@ void StageSchematicScene::onEditGroup() { TStageObjectId StageSchematicScene::getCurrentObject() { return m_objHandle->getObjectId(); } + +//------------------------------------------------------------------ + +void StageSchematicScene::onNodeChangedSize() { + if (resizingNodes) return; + updateScene(); +} diff --git a/toonz/sources/toonzqt/studiopaletteviewer.cpp b/toonz/sources/toonzqt/studiopaletteviewer.cpp index a033f05..25f1419 100644 --- a/toonz/sources/toonzqt/studiopaletteviewer.cpp +++ b/toonz/sources/toonzqt/studiopaletteviewer.cpp @@ -1191,17 +1191,17 @@ StudioPaletteViewer::StudioPaletteViewer(QWidget *parent, treeWidget->setLayout(treeVLayout); // Second Splitter Widget - PaletteViewer *studioPaletteViewer = + m_studioPaletteViewer = new PaletteViewer(this, PaletteViewerGUI::STUDIO_PALETTE); - studioPaletteViewer->setObjectName("PaletteViewerInStudioPalette"); - studioPaletteViewer->setXsheetHandle(xsheetHandle); - studioPaletteViewer->setPaletteHandle(studioPaletteHandle); - studioPaletteViewer->setFrameHandle(frameHandle); + m_studioPaletteViewer->setObjectName("PaletteViewerInStudioPalette"); + m_studioPaletteViewer->setXsheetHandle(xsheetHandle); + m_studioPaletteViewer->setPaletteHandle(studioPaletteHandle); + m_studioPaletteViewer->setFrameHandle(frameHandle); addWidget(treeWidget); - addWidget(studioPaletteViewer); + addWidget(m_studioPaletteViewer); - setFocusProxy(studioPaletteViewer); + setFocusProxy(m_studioPaletteViewer); } //----------------------------------------------------------------------------- @@ -1214,3 +1214,16 @@ StudioPaletteViewer::~StudioPaletteViewer() {} TFilePath StudioPaletteViewer::getCurrentItemPath() { return m_studioPaletteTreeViewer->getCurrentItemPath(); } + +//----------------------------------------------------------------------------- + +int StudioPaletteViewer::getViewMode() const { + return m_studioPaletteViewer->getViewMode(); +} + +//----------------------------------------------------------------------------- + +void StudioPaletteViewer::setViewMode(int mode) { + m_studioPaletteViewer->setViewMode( + (PaletteViewerGUI::PageViewer::ViewMode)mode); +} \ No newline at end of file diff --git a/toonz/sources/toonzqt/styleeditor.cpp b/toonz/sources/toonzqt/styleeditor.cpp index 2f3717b..fa4df3f 100644 --- a/toonz/sources/toonzqt/styleeditor.cpp +++ b/toonz/sources/toonzqt/styleeditor.cpp @@ -3254,9 +3254,9 @@ void StyleEditor::showEvent(QShowEvent *) { //----------------------------------------------------------------------------- void StyleEditor::hideEvent(QHideEvent *) { - disconnect(m_paletteHandle); - if (m_cleanupPaletteHandle) disconnect(m_cleanupPaletteHandle); - disconnect(m_paletteController); + disconnect(m_paletteHandle, 0, this, 0); + if (m_cleanupPaletteHandle) disconnect(m_cleanupPaletteHandle, 0, this, 0); + disconnect(m_paletteController, 0, this, 0); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonzqt/styleindexlineedit.cpp b/toonz/sources/toonzqt/styleindexlineedit.cpp index e2a67fb..f294d58 100644 --- a/toonz/sources/toonzqt/styleindexlineedit.cpp +++ b/toonz/sources/toonzqt/styleindexlineedit.cpp @@ -30,6 +30,8 @@ StyleIndexLineEdit::~StyleIndexLineEdit() {} void StyleIndexLineEdit::paintEvent(QPaintEvent *pe) { QLineEdit::paintEvent(pe); + if (!m_pltHandle->getPalette()) return; + TColorStyle *style; // Aware of both "current" and translated string if (QString("current").contains(text()) || tr("current").contains(text())) diff --git a/toonz/sources/translations/chinese/image.ts b/toonz/sources/translations/chinese/image.ts index 85cd0b3..b2b5de1 100644 --- a/toonz/sources/translations/chinese/image.ts +++ b/toonz/sources/translations/chinese/image.ts @@ -4,12 +4,12 @@ AviWriterProperties - + Codec 编码器 - + Uncompressed 未压缩 @@ -70,54 +70,54 @@ Please try raising the FFmpeg timeout in Preferences. SgiWriterProperties - + Bits Per Pixel 像素位数 - + 24 bits 24 位 - + 32 bits 32 位 - + 48 bits 48 位 - + 64 bits 64 位 - + 8 bits (Greyscale) 8 位(灰阶) - + Endianess 字节序 - + Big Endian 高地址位在整个地址位的前端低位优先 高位优先 - + Little Endian 代表低地址位在整个地址位的前端 低位优先 - + RLE-Compressed RLE 压缩 @@ -183,37 +183,37 @@ Please try raising the FFmpeg timeout in Preferences. SvgWriterProperties - + Stroke Mode 描边模式 - + Outline Quality 轮廓质量 - + Centerline 中心线 - + Outline 轮廓 - + High - + Medium - + Low @@ -342,12 +342,12 @@ Please try raising the FFmpeg timeout in Preferences. WebmWriterProperties - + Quality 质量 - + Scale 缩放 diff --git a/toonz/sources/translations/chinese/tnztools.ts b/toonz/sources/translations/chinese/tnztools.ts index 1ca6d7c..407a733 100644 --- a/toonz/sources/translations/chinese/tnztools.ts +++ b/toonz/sources/translations/chinese/tnztools.ts @@ -96,7 +96,7 @@ Hardness: - 硬度: + 硬度: Accuracy: @@ -144,7 +144,7 @@ Pencil - 铅笔 + 铅笔 Pressure @@ -224,19 +224,19 @@ Draw Order: - 绘制顺序: + 绘制顺序: Over All - 在最上 + 在最上 Under All - 在最下 + 在最下 Palette Order - 按调色板顺序 + 按调色板顺序 @@ -1345,6 +1345,33 @@ Do you want to proceed? Link 保持长宽比 + + Scale + 缩放 + + + Position + 位置 + + + + ShiftTraceToolOptionBox + + Reset Previous + + + + Reset Following + + + + Previous Drawing + + + + Following Drawing + + SkeletonTool @@ -1425,6 +1452,53 @@ moved to the end of the first page of the palette. + ToonzRasterBrushTool + + Size + 大小 + + + Hardness: + 硬度: + + + Smooth: + 平滑: + + + Draw Order: + 绘制顺序: + + + Over All + 在最上 + + + Under All + 在最下 + + + Palette Order + 按调色板顺序 + + + Preset: + 预设: + + + <custom> + <定制> + + + Pencil + 铅笔 + + + Pressure + 压感 + + + TrackerTool Width: diff --git a/toonz/sources/translations/chinese/toonz.ts b/toonz/sources/translations/chinese/toonz.ts index 44ec0e3..a7a7bcd 100644 --- a/toonz/sources/translations/chinese/toonz.ts +++ b/toonz/sources/translations/chinese/toonz.ts @@ -374,6 +374,92 @@ Stop it or wait for its completion before removing it. + BoardSettingsPopup + + Clapperboard Settings + + + + Load Preset + + + + Save as Preset + + + + Close + 关闭 + + + Duration (frames): + + + + Text + + + + Project name + + + + Scene name + + + + Duration : Frame + + + + Duration : Sec + Frame + + + + Duration : HH:MM:SS:FF + + + + Current date + + + + Current date and time + + + + User name + + + + Scene location : Aliased path + + + + Scene location : Full path + + + + Output location : Aliased path + + + + Output location : Full path + + + + Image + + + + + BoardView + + Please set the duration more than 0 frame first, or the clapperboard settings will not be saved in the scene at all! + + + + BrightnessAndContrastPopup Brightness and Contrast @@ -2268,6 +2354,25 @@ contain the dpi information, then the current camera dpi will be used. Drag to Extend Onion Skin, Double Click to Toggle All [拖动]以扩展洋葱皮,[双击]以切换所有洋葱皮 + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + Click to Move Shift & Trace Marker + + FilmstripFrames @@ -2535,6 +2640,76 @@ Do you want to overwrite it? + ItemInfoView + + Bold + + + + Italic + + + + Ignore + + + + Keep + + + + Name: + 名称: + + + Type: + 类型: + + + Path: + 路径: + + + Aspect Ratio: + + + + Font: + + + + Max Size: + + + + No item selected. + + + + Item + + + + + ItemListView + + Add + 添加 + + + Remove + + + + Move Up + + + + Move Down + + + + LayerFooterPanel Zoom in/out of timeline @@ -3033,6 +3208,13 @@ Please use the frame numbers for reference. + LoadBoardPresetFilePopup + + Load Clapperboard Settings Preset + + + + LoadColorModelPopup Load Color Model @@ -5159,7 +5341,7 @@ Please use the frame numbers for reference. Flip Viewer Horiontally - 水平翻转查看器 + 水平翻转查看器 Flip Viewer Vertically @@ -5213,6 +5395,50 @@ Please use the frame numbers for reference. Active Axis - All 当前轴 - 全部 + + &Timeline + + + + Linear Interpolation + + + + Speed In / Speed Out Interpolation + + + + Ease In / Ease Out Interpolation + + + + Ease In / Ease Out (%) Interpolation + + + + Exponential Interpolation + + + + Expression Interpolation + + + + File Interpolation + + + + Constant Interpolation + + + + Separate Colors... + + + + Flip Viewer Horizontally + + MatchlinesDialog @@ -5792,6 +6018,25 @@ What do you want to do? Render 渲染 + + Add Clapperboard + + + + Edit Clapperboard... + + + + Save current output settings. +The parameters to be saved are: +- Camera settings +- Project folder to be saved in +- File format +- File options +- Resample Balance +- Channel width + + OverwriteDialog @@ -7239,7 +7484,7 @@ if both are possible on coding file path. Weight *: - 粗细 *: + 粗细 *: OpenToonz can use FFmpeg for additional file formats. @@ -7347,6 +7592,55 @@ Also the initial output destination for new scenes will be set to $scenefolder a Compact 兼容 + + Saving + + + + Use Onion Skin Colors for Reference Drawings of Shift and Trace + + + + Tablet Settings + + + + Enable Windows Ink Support* (EXPERIMENTAL) + + + + Constant + + + + Exponential + + + + Expression + + + + File + 文件 + + + Style *: + + + + Matte color is used for background when overwriting raster levels with transparent pixels +in non alpha-enabled image format. + + + + Matte color: + + + + Current Column Color: + + PreferencesPopup::FormatProperties @@ -8203,7 +8497,7 @@ Some levels have not been loaded because their version is not supported The Revert to Last Saved command is not supported for the current selection. - 当前选区不支持复原到最后保存的命令。 + 当前选区不支持复原到最后保存的命令。 The selected column is empty. @@ -9244,6 +9538,67 @@ Allow duplicate? Nothing to replace: no cells or columns selected. 没有可替换的: 没有帧格或者列被选中。 + + Couldn't load %1 + + + + Apply Antialias + 应用消除锯齿 + + + The Reload command is not supported for the current selection. + + + + Error + + + + No Palette loaded. + + + + A separation task is in progress! wait until it stops or cancel it + + + + Duplicate Frame in XSheet + + + + Please enable "Sync Level Strip Drawing Number Changes with the XSheet" preference option +to use the duplicate command in the xsheet / timeline. + + + + Please select only one layer to duplicate a frame. + + + + Please select only one frame to duplicate. + + + + Timeline + + + + The qualifier %1 is not a valid key name. Skipping. + + + + Clear All Onion Skin Markers + + + + Clear All Fixed Onion Skin Markers + + + + Clear All Relative Onion Skin Markers + + ReframePopup @@ -10236,6 +10591,13 @@ Please commit or revert changes first. + SaveBoardPresetFilePopup + + Save Clapperboard Settings As Preset + + + + SaveCurvePopup Save Curve @@ -10642,6 +11004,172 @@ Please commit or revert changes first. + SeparateColorsPopup + + Auto + 自动 + + + Preview + 预览 + + + Separate + + + + Close + 关闭 + + + Sub Color 3: + + + + Alpha Matting + + + + Main + + + + Sub1 + + + + Sub2 + + + + Sub3 + + + + Pick Color + + + + Show Mask + + + + Show Alpha + + + + Preview Frame: + + + + Paper Color: + + + + Main Color: + + + + Sub Color 1: + + + + Sub Color 2: + + + + Sub Adjust: + + + + Border Smooth: + + + + Mask Threshold: + + + + Mask Radius: + + + + Start: + 开始: + + + End: + + + + Format: + 格式: + + + Save in: + 保存位置: + + + File Suffix: + + + + Cancel + 取消 + + + Separate by colors ... + + + + Separate 1 Level + + + + Separate %1 Levels + + + + Critical + + + + Failed to access the destination folder! + + + + Separating %1 + + + + Converting level %1 of %2: %3 + %1 / %2 正在转换层级: %3 + + + + SeparateSwatch + + Sub Color 3 + + + + Original + + + + Main Color + + + + Sub Color 1 + + + + Sub Color 2 + + + + ShortcutPopup Configure Shortcuts @@ -12095,6 +12623,10 @@ Please refer to the user guide for details. Filter: 过滤器: + + Opacity: + + XsheetGUI::NoteArea @@ -12114,6 +12646,22 @@ Please refer to the user guide for details. 3sec Sheet 3秒表 + + Toggle Xsheet/Timeline + + + + Add New Memo + + + + Previous Memo + + + + Next Memo + + XsheetGUI::NotePopup @@ -12188,6 +12736,32 @@ Please refer to the user guide for details. Set Auto Markers 设置自动标注 + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + Click to Move Shift & Trace Marker + + + + + XsheetGUI::SoundColumnPopup + + Volume: + + XsheetGUI::Toolbar diff --git a/toonz/sources/translations/chinese/toonzqt.ts b/toonz/sources/translations/chinese/toonzqt.ts index b4315bd..715e6f1 100644 --- a/toonz/sources/translations/chinese/toonzqt.ts +++ b/toonz/sources/translations/chinese/toonzqt.ts @@ -262,7 +262,7 @@ Possibly the preset file has been corrupted &Open Subxsheet - 打开子摄影表(&O) + 打开子摄影表(&O) @@ -703,6 +703,17 @@ Possibly the preset file has been corrupted + FontParamField + + Style: + + + + Size: + + + + FrameNavigator Previous Frame @@ -1092,7 +1103,7 @@ Possibly the preset file has been corrupted &Open Subxsheet - 打开子摄影表(&O) + 打开子摄影表(&O) &Uncache Fx @@ -1212,6 +1223,13 @@ Possibly the preset file has been corrupted + FxSchematicOutputNode + + Output + 输出 + + + FxSchematicPort &Disconnect from Xsheet @@ -1244,6 +1262,13 @@ Select FX nodes and related links before copying or cutting the selection you wa + FxSchematicXSheetNode + + XSheet + 摄影表 + + + FxSettings &Camera Preview @@ -2235,6 +2260,10 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< &Swtich output port display mode 切换输出端口显示模式(&S) + + &Toggle node icons + + SchematicWindowEditor diff --git a/toonz/sources/translations/french/image.ts b/toonz/sources/translations/french/image.ts index 73006fb..b08615c 100644 --- a/toonz/sources/translations/french/image.ts +++ b/toonz/sources/translations/french/image.ts @@ -4,12 +4,12 @@ AviWriterProperties - + Codec - + Uncompressed @@ -67,52 +67,52 @@ Please try raising the FFmpeg timeout in Preferences. SgiWriterProperties - + Bits Per Pixel - + 24 bits - + 32 bits - + 48 bits - + 64 bits - + 8 bits (Greyscale) - + Endianess - + Big Endian - + Little Endian - + RLE-Compressed @@ -178,37 +178,37 @@ Please try raising the FFmpeg timeout in Preferences. SvgWriterProperties - + Stroke Mode - + Outline Quality - + Centerline - + Outline - + High - + Medium - + Low @@ -337,12 +337,12 @@ Please try raising the FFmpeg timeout in Preferences. WebmWriterProperties - + Quality - + Scale diff --git a/toonz/sources/translations/french/tnztools.ts b/toonz/sources/translations/french/tnztools.ts index 889d974..e6ae44b 100644 --- a/toonz/sources/translations/french/tnztools.ts +++ b/toonz/sources/translations/french/tnztools.ts @@ -96,7 +96,7 @@ Hardness: - Dureté: + Dureté: Accuracy: @@ -143,10 +143,6 @@ - Pencil - - - Pressure @@ -222,22 +218,6 @@ Med - - Draw Order: - - - - Over All - - - - Under All - - - - Palette Order - - BrushToolOptionsBox @@ -1342,6 +1322,33 @@ Voulez-vous continuer? Link Lier + + Scale + Échelle + + + Position + Position + + + + ShiftTraceToolOptionBox + + Reset Previous + + + + Reset Following + + + + Previous Drawing + + + + Following Drawing + + SkeletonTool @@ -1422,6 +1429,53 @@ moved to the end of the first page of the palette. + ToonzRasterBrushTool + + Size + + + + Hardness: + Dureté: + + + Smooth: + + + + Draw Order: + + + + Over All + + + + Under All + + + + Palette Order + + + + Preset: + Paramètre Prédéfini: + + + <custom> + + + + Pencil + + + + Pressure + + + + TrackerTool Width: diff --git a/toonz/sources/translations/french/toonz.ts b/toonz/sources/translations/french/toonz.ts index 89e3899..80c517d 100644 --- a/toonz/sources/translations/french/toonz.ts +++ b/toonz/sources/translations/french/toonz.ts @@ -365,6 +365,92 @@ Arrête ou attendre son achèvement avant de le retirer. + BoardSettingsPopup + + Clapperboard Settings + + + + Load Preset + + + + Save as Preset + + + + Close + Fermer + + + Duration (frames): + + + + Text + + + + Project name + + + + Scene name + + + + Duration : Frame + + + + Duration : Sec + Frame + + + + Duration : HH:MM:SS:FF + + + + Current date + + + + Current date and time + + + + User name + + + + Scene location : Aliased path + + + + Scene location : Full path + + + + Output location : Aliased path + + + + Output location : Full path + + + + Image + + + + + BoardView + + Please set the duration more than 0 frame first, or the clapperboard settings will not be saved in the scene at all! + + + + BrightnessAndContrastPopup Brightness and Contrast @@ -2225,6 +2311,25 @@ contain the dpi information, then the current camera dpi will be used. Drag to Extend Onion Skin, Double Click to Toggle All + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + Click to Move Shift & Trace Marker + + FilmstripFrames @@ -2492,6 +2597,76 @@ Do you want to overwrite it? + ItemInfoView + + Bold + + + + Italic + + + + Ignore + + + + Keep + + + + Name: + Nom: + + + Type: + Type: + + + Path: + Chemin: + + + Aspect Ratio: + + + + Font: + + + + Max Size: + + + + No item selected. + + + + Item + + + + + ItemListView + + Add + Ajouter + + + Remove + Retirer + + + Move Up + + + + Move Down + + + + LayerFooterPanel Zoom in/out of timeline @@ -2988,6 +3163,13 @@ Please use the frame numbers for reference. + LoadBoardPresetFilePopup + + Load Clapperboard Settings Preset + + + + LoadColorModelPopup Load Color Model @@ -5090,10 +5272,6 @@ Please use the frame numbers for reference. - Flip Viewer Horiontally - - - Flip Viewer Vertically @@ -5153,6 +5331,50 @@ Please use the frame numbers for reference. Active Axis - All + + &Timeline + + + + Linear Interpolation + + + + Speed In / Speed Out Interpolation + + + + Ease In / Ease Out Interpolation + + + + Ease In / Ease Out (%) Interpolation + + + + Exponential Interpolation + + + + Expression Interpolation + + + + File Interpolation + + + + Constant Interpolation + + + + Separate Colors... + + + + Flip Viewer Horizontally + + MatchlinesDialog @@ -5726,6 +5948,25 @@ Que voulez-vous faire? Render + + Add Clapperboard + + + + Edit Clapperboard... + + + + Save current output settings. +The parameters to be saved are: +- Camera settings +- Project folder to be saved in +- File format +- File options +- Resample Balance +- Channel width + + OverwriteDialog @@ -7074,10 +7315,6 @@ if both are possible on coding file path. - Weight *: - - - OpenToonz can use FFmpeg for additional file formats. @@ -7180,6 +7417,55 @@ Also the initial output destination for new scenes will be set to $scenefolder a Compact + + Saving + + + + Use Onion Skin Colors for Reference Drawings of Shift and Trace + + + + Tablet Settings + + + + Enable Windows Ink Support* (EXPERIMENTAL) + + + + Constant + + + + Exponential + + + + Expression + + + + File + Fichier + + + Style *: + + + + Matte color is used for background when overwriting raster levels with transparent pixels +in non alpha-enabled image format. + + + + Matte color: + + + + Current Column Color: + + PreferencesPopup::FormatProperties @@ -8050,7 +8336,7 @@ Certains niveaux n'ont pas été chargés, car leur version n'est pas The Revert to Last Saved command is not supported for the current selection. - La commande Revenir à la Dernière Version Enregistrée n'est pas disponible pour la sélection courante. + La commande Revenir à la Dernière Version Enregistrée n'est pas disponible pour la sélection courante. The selected column is empty. @@ -9016,6 +9302,67 @@ Allow duplicate? Nothing to replace: no cells or columns selected. + + Couldn't load %1 + + + + Apply Antialias + Appliquer Antialias + + + The Reload command is not supported for the current selection. + + + + Error + + + + No Palette loaded. + + + + A separation task is in progress! wait until it stops or cancel it + + + + Duplicate Frame in XSheet + + + + Please enable "Sync Level Strip Drawing Number Changes with the XSheet" preference option +to use the duplicate command in the xsheet / timeline. + + + + Please select only one layer to duplicate a frame. + + + + Please select only one frame to duplicate. + + + + Timeline + + + + The qualifier %1 is not a valid key name. Skipping. + + + + Clear All Onion Skin Markers + + + + Clear All Fixed Onion Skin Markers + + + + Clear All Relative Onion Skin Markers + + ReframePopup @@ -10003,6 +10350,13 @@ S'il vous plaît commettre ou annuler les modifications avant. + SaveBoardPresetFilePopup + + Save Clapperboard Settings As Preset + + + + SaveCurvePopup Save Curve @@ -10397,6 +10751,172 @@ S'il vous plaît commettre ou annuler les modifications avant. + SeparateColorsPopup + + Auto + Auto + + + Preview + Preview + + + Separate + + + + Close + Fermer + + + Sub Color 3: + + + + Alpha Matting + + + + Main + + + + Sub1 + + + + Sub2 + + + + Sub3 + + + + Pick Color + + + + Show Mask + + + + Show Alpha + + + + Preview Frame: + + + + Paper Color: + + + + Main Color: + + + + Sub Color 1: + + + + Sub Color 2: + + + + Sub Adjust: + + + + Border Smooth: + + + + Mask Threshold: + + + + Mask Radius: + + + + Start: + Début: + + + End: + Fin: + + + Format: + Format: + + + Save in: + Enregistrer dans: + + + File Suffix: + + + + Cancel + Annuler + + + Separate by colors ... + + + + Separate 1 Level + + + + Separate %1 Levels + + + + Critical + + + + Failed to access the destination folder! + + + + Separating %1 + + + + Converting level %1 of %2: %3 + Conversion du niveau %1 de %2: %3 + + + + SeparateSwatch + + Sub Color 3 + + + + Original + + + + Main Color + + + + Sub Color 1 + + + + Sub Color 2 + + + + ShortcutPopup Configure Shortcuts @@ -11726,6 +12246,10 @@ S'il vous plaît se référer à la guide de l'utilisateur pour plus d Filter: + + Opacity: + + XsheetGUI::NoteArea @@ -11745,6 +12269,22 @@ S'il vous plaît se référer à la guide de l'utilisateur pour plus d 3sec Sheet + + Toggle Xsheet/Timeline + + + + Add New Memo + + + + Previous Memo + + + + Next Memo + + XsheetGUI::NotePopup @@ -11815,6 +12355,32 @@ S'il vous plaît se référer à la guide de l'utilisateur pour plus d Set Auto Markers + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + Click to Move Shift & Trace Marker + + + + + XsheetGUI::SoundColumnPopup + + Volume: + + XsheetGUI::XSheetToolbar diff --git a/toonz/sources/translations/french/toonzqt.ts b/toonz/sources/translations/french/toonzqt.ts index 56d4253..87b0f8e 100644 --- a/toonz/sources/translations/french/toonzqt.ts +++ b/toonz/sources/translations/french/toonzqt.ts @@ -256,7 +256,7 @@ Possibly the preset file has been corrupted &Open Subxsheet - &Ouvrir le Sub-xsheet + &Ouvrir le Sub-xsheet @@ -697,6 +697,17 @@ Possibly the preset file has been corrupted + FontParamField + + Style: + + + + Size: + + + + FrameNavigator Previous Frame @@ -1086,7 +1097,7 @@ Possibly the preset file has been corrupted &Open Subxsheet - &Ouvrir le Sub-xsheet + &Ouvrir le Sub-xsheet &Uncache Fx @@ -1202,6 +1213,13 @@ Possibly the preset file has been corrupted + FxSchematicOutputNode + + Output + + + + FxSchematicPort &Disconnect from Xsheet @@ -1234,6 +1252,13 @@ Sélectionnez les nœuds FX et les liens connexes avant de copier ou couper la s + FxSchematicXSheetNode + + XSheet + + + + FxSettings &Camera Preview @@ -2164,6 +2189,10 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< &Swtich output port display mode + + &Toggle node icons + + SchematicWindowEditor diff --git a/toonz/sources/translations/german/image.ts b/toonz/sources/translations/german/image.ts index 73006fb..b08615c 100644 --- a/toonz/sources/translations/german/image.ts +++ b/toonz/sources/translations/german/image.ts @@ -4,12 +4,12 @@ AviWriterProperties - + Codec - + Uncompressed @@ -67,52 +67,52 @@ Please try raising the FFmpeg timeout in Preferences. SgiWriterProperties - + Bits Per Pixel - + 24 bits - + 32 bits - + 48 bits - + 64 bits - + 8 bits (Greyscale) - + Endianess - + Big Endian - + Little Endian - + RLE-Compressed @@ -178,37 +178,37 @@ Please try raising the FFmpeg timeout in Preferences. SvgWriterProperties - + Stroke Mode - + Outline Quality - + Centerline - + Outline - + High - + Medium - + Low @@ -337,12 +337,12 @@ Please try raising the FFmpeg timeout in Preferences. WebmWriterProperties - + Quality - + Scale diff --git a/toonz/sources/translations/german/tnztools.ts b/toonz/sources/translations/german/tnztools.ts index db70fde..a770247 100644 --- a/toonz/sources/translations/german/tnztools.ts +++ b/toonz/sources/translations/german/tnztools.ts @@ -96,7 +96,7 @@ Hardness: - Härte: + Härte: Accuracy: @@ -144,7 +144,7 @@ Pencil - Bleistift Modus + Bleistift Modus Pressure @@ -222,22 +222,6 @@ Med - - Draw Order: - - - - Over All - - - - Under All - - - - Palette Order - - BrushToolOptionsBox @@ -1341,6 +1325,33 @@ Möchten Sie fortfahren? Link Seitenverhältnis festlegen + + Scale + Maßstab + + + Position + Position + + + + ShiftTraceToolOptionBox + + Reset Previous + + + + Reset Following + + + + Previous Drawing + + + + Following Drawing + + SkeletonTool @@ -1421,6 +1432,53 @@ moved to the end of the first page of the palette. + ToonzRasterBrushTool + + Size + Größe + + + Hardness: + Härte: + + + Smooth: + + + + Draw Order: + + + + Over All + + + + Under All + + + + Palette Order + + + + Preset: + Vorlage: + + + <custom> + + + + Pencil + Bleistift Modus + + + Pressure + Druck + + + TrackerTool Width: diff --git a/toonz/sources/translations/german/toonz.ts b/toonz/sources/translations/german/toonz.ts index 55c4910..f829f7b 100644 --- a/toonz/sources/translations/german/toonz.ts +++ b/toonz/sources/translations/german/toonz.ts @@ -362,6 +362,92 @@ Halten Sie sie an oder warten Sie auf ihre Beendung bevor Sie sie entwenden. + BoardSettingsPopup + + Clapperboard Settings + + + + Load Preset + + + + Save as Preset + + + + Close + Schließen + + + Duration (frames): + + + + Text + + + + Project name + + + + Scene name + + + + Duration : Frame + + + + Duration : Sec + Frame + + + + Duration : HH:MM:SS:FF + + + + Current date + + + + Current date and time + + + + User name + + + + Scene location : Aliased path + + + + Scene location : Full path + + + + Output location : Aliased path + + + + Output location : Full path + + + + Image + + + + + BoardView + + Please set the duration more than 0 frame first, or the clapperboard settings will not be saved in the scene at all! + + + + BrightnessAndContrastPopup Brightness and Contrast @@ -2307,6 +2393,25 @@ contain the dpi information, then the current camera dpi will be used. Drag to Extend Onion Skin, Double Click to Toggle All Ziehen Sie um die Onion Skin zu erweitern, Doppel-Klicken Sie um Alle umzuschalten + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + Click to Move Shift & Trace Marker + + FilmstripFrames @@ -2621,6 +2726,76 @@ Do you want to overwrite it? + ItemInfoView + + Bold + + + + Italic + + + + Ignore + + + + Keep + + + + Name: + + + + Type: + Typ: + + + Path: + Pfad: + + + Aspect Ratio: + + + + Font: + + + + Max Size: + + + + No item selected. + + + + Item + + + + + ItemListView + + Add + Hinzufügen + + + Remove + + + + Move Up + + + + Move Down + + + + LayerFooterPanel Zoom in/out of timeline @@ -3121,6 +3296,13 @@ Please use the frame numbers for reference. + LoadBoardPresetFilePopup + + Load Clapperboard Settings Preset + + + + LoadColorModelPopup Load Color Model @@ -5247,10 +5429,6 @@ Please use the frame numbers for reference. - Flip Viewer Horiontally - - - Flip Viewer Vertically @@ -5310,6 +5488,50 @@ Please use the frame numbers for reference. Active Axis - All + + &Timeline + + + + Linear Interpolation + + + + Speed In / Speed Out Interpolation + + + + Ease In / Ease Out Interpolation + + + + Ease In / Ease Out (%) Interpolation + + + + Exponential Interpolation + + + + Expression Interpolation + + + + File Interpolation + + + + Constant Interpolation + + + + Separate Colors... + + + + Flip Viewer Horizontally + + MatchlinesDialog @@ -5886,6 +6108,25 @@ Was möchten Sie tun? Render Render + + Add Clapperboard + + + + Edit Clapperboard... + + + + Save current output settings. +The parameters to be saved are: +- Camera settings +- Project folder to be saved in +- File format +- File options +- Resample Balance +- Channel width + + OverwriteDialog @@ -7281,10 +7522,6 @@ if both are possible on coding file path. - Weight *: - - - OpenToonz can use FFmpeg for additional file formats. @@ -7387,6 +7624,55 @@ Also the initial output destination for new scenes will be set to $scenefolder a Compact + + Saving + + + + Use Onion Skin Colors for Reference Drawings of Shift and Trace + + + + Tablet Settings + + + + Enable Windows Ink Support* (EXPERIMENTAL) + + + + Constant + + + + Exponential + + + + Expression + + + + File + Datei + + + Style *: + + + + Matte color is used for background when overwriting raster levels with transparent pixels +in non alpha-enabled image format. + + + + Matte color: + + + + Current Column Color: + + PreferencesPopup:: FormatProperties @@ -8273,7 +8559,7 @@ Einige Ebenen wurden nicht geladen, da ihre Version nicht unterstützt wird The Revert to Last Saved command is not supported for the current selection. - Der "Zur zuletzt gespeicherten Version zurücksetzen" Befehl wird nicht für die aktuelle Auswahl unterstützt. + Der "Zur zuletzt gespeicherten Version zurücksetzen" Befehl wird nicht für die aktuelle Auswahl unterstützt. The selected column is empty. @@ -9305,6 +9591,67 @@ Allow duplicate? Nothing to replace: no cells or columns selected. Es gibt nichts zum ersetzen: Es wurden weder Cells noch Spalten gewählt. + + Couldn't load %1 + + + + Apply Antialias + Kantenglättung anwenden + + + The Reload command is not supported for the current selection. + + + + Error + + + + No Palette loaded. + + + + A separation task is in progress! wait until it stops or cancel it + + + + Duplicate Frame in XSheet + + + + Please enable "Sync Level Strip Drawing Number Changes with the XSheet" preference option +to use the duplicate command in the xsheet / timeline. + + + + Please select only one layer to duplicate a frame. + + + + Please select only one frame to duplicate. + + + + Timeline + + + + The qualifier %1 is not a valid key name. Skipping. + + + + Clear All Onion Skin Markers + + + + Clear All Fixed Onion Skin Markers + + + + Clear All Relative Onion Skin Markers + + ReframePopup @@ -10305,6 +10652,13 @@ Bitte tragen Sie die Änderungen ein oder setzen sie zurück. + SaveBoardPresetFilePopup + + Save Clapperboard Settings As Preset + + + + SaveCurvePopup Save Curve @@ -10703,6 +11057,172 @@ Bitte tragen Sie die Änderungen ein oder setzen sie zurück. + SeparateColorsPopup + + Auto + Automatisch + + + Preview + Vorschau + + + Separate + + + + Close + Schließen + + + Sub Color 3: + + + + Alpha Matting + + + + Main + + + + Sub1 + + + + Sub2 + + + + Sub3 + + + + Pick Color + + + + Show Mask + + + + Show Alpha + + + + Preview Frame: + + + + Paper Color: + + + + Main Color: + + + + Sub Color 1: + + + + Sub Color 2: + + + + Sub Adjust: + + + + Border Smooth: + + + + Mask Threshold: + + + + Mask Radius: + + + + Start: + Start: + + + End: + + + + Format: + Format: + + + Save in: + Speichern in: + + + File Suffix: + + + + Cancel + Abbrechen + + + Separate by colors ... + + + + Separate 1 Level + + + + Separate %1 Levels + + + + Critical + + + + Failed to access the destination folder! + + + + Separating %1 + + + + Converting level %1 of %2: %3 + Wandle Ebene %1 von %2 um: %3 + + + + SeparateSwatch + + Sub Color 3 + + + + Original + + + + Main Color + + + + Sub Color 1 + + + + Sub Color 2 + + + + ShortcutPopup Configure Shortcuts @@ -12042,6 +12562,10 @@ Genaueres können Sie aus der Nutzerhilfe entnehmen. Filter: + + Opacity: + + XsheetGUI::NoteArea @@ -12061,6 +12585,22 @@ Genaueres können Sie aus der Nutzerhilfe entnehmen. 3sec Sheet 3 Sekunden Xsheet + + Toggle Xsheet/Timeline + + + + Add New Memo + + + + Previous Memo + + + + Next Memo + + XsheetGUI::NotePopup @@ -12135,6 +12675,32 @@ Genaueres können Sie aus der Nutzerhilfe entnehmen. Set Auto Markers + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + Click to Move Shift & Trace Marker + + + + + XsheetGUI::SoundColumnPopup + + Volume: + + XsheetGUI::XSheetToolbar diff --git a/toonz/sources/translations/german/toonzqt.ts b/toonz/sources/translations/german/toonzqt.ts index ad0cf0f..8023f9d 100644 --- a/toonz/sources/translations/german/toonzqt.ts +++ b/toonz/sources/translations/german/toonzqt.ts @@ -259,7 +259,7 @@ Possibly the preset file has been corrupted &Open Subxsheet - Xsheet öffnen (&O) + Xsheet öffnen (&O) @@ -704,6 +704,17 @@ Possibly the preset file has been corrupted + FontParamField + + Style: + + + + Size: + + + + FrameNavigator Previous Frame @@ -1093,7 +1104,7 @@ Possibly the preset file has been corrupted &Open Subxsheet - Xsheet öffnen (&O) + Xsheet öffnen (&O) &Uncache Fx @@ -1213,6 +1224,13 @@ Possibly the preset file has been corrupted + FxSchematicOutputNode + + Output + Output + + + FxSchematicPort &Disconnect from Xsheet @@ -1245,6 +1263,13 @@ Wählen Sie Effekt-Nodes und verwandte Links, die Sie einfügen möchten, bevor + FxSchematicXSheetNode + + XSheet + XSheet + + + FxSettings &Camera Preview @@ -2211,6 +2236,10 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< &Swtich output port display mode + + &Toggle node icons + + SchematicWindowEditor diff --git a/toonz/sources/translations/italian/image.ts b/toonz/sources/translations/italian/image.ts index 73006fb..b08615c 100644 --- a/toonz/sources/translations/italian/image.ts +++ b/toonz/sources/translations/italian/image.ts @@ -4,12 +4,12 @@ AviWriterProperties - + Codec - + Uncompressed @@ -67,52 +67,52 @@ Please try raising the FFmpeg timeout in Preferences. SgiWriterProperties - + Bits Per Pixel - + 24 bits - + 32 bits - + 48 bits - + 64 bits - + 8 bits (Greyscale) - + Endianess - + Big Endian - + Little Endian - + RLE-Compressed @@ -178,37 +178,37 @@ Please try raising the FFmpeg timeout in Preferences. SvgWriterProperties - + Stroke Mode - + Outline Quality - + Centerline - + Outline - + High - + Medium - + Low @@ -337,12 +337,12 @@ Please try raising the FFmpeg timeout in Preferences. WebmWriterProperties - + Quality - + Scale diff --git a/toonz/sources/translations/italian/tnztools.ts b/toonz/sources/translations/italian/tnztools.ts index b5ca4ba..5bb2860 100644 --- a/toonz/sources/translations/italian/tnztools.ts +++ b/toonz/sources/translations/italian/tnztools.ts @@ -96,7 +96,7 @@ Hardness: - Durezza: + Durezza: Accuracy: @@ -143,10 +143,6 @@ - Pencil - - - Pressure @@ -222,22 +218,6 @@ Med - - Draw Order: - - - - Over All - - - - Under All - - - - Palette Order - - BrushToolOptionsBox @@ -1340,6 +1320,33 @@ Procedere? Link Vincola + + Scale + Scala + + + Position + Posizione + + + + ShiftTraceToolOptionBox + + Reset Previous + + + + Reset Following + + + + Previous Drawing + + + + Following Drawing + + SkeletonTool @@ -1420,6 +1427,53 @@ moved to the end of the first page of the palette. + ToonzRasterBrushTool + + Size + + + + Hardness: + Durezza: + + + Smooth: + + + + Draw Order: + + + + Over All + + + + Under All + + + + Palette Order + + + + Preset: + + + + <custom> + + + + Pencil + + + + Pressure + + + + TrackerTool Width: diff --git a/toonz/sources/translations/italian/toonz.ts b/toonz/sources/translations/italian/toonz.ts index 1b367d2..42484d6 100644 --- a/toonz/sources/translations/italian/toonz.ts +++ b/toonz/sources/translations/italian/toonz.ts @@ -364,6 +364,92 @@ Stop it or wait for its completion before removing it. + BoardSettingsPopup + + Clapperboard Settings + + + + Load Preset + + + + Save as Preset + + + + Close + Chiudi + + + Duration (frames): + + + + Text + + + + Project name + + + + Scene name + + + + Duration : Frame + + + + Duration : Sec + Frame + + + + Duration : HH:MM:SS:FF + + + + Current date + + + + Current date and time + + + + User name + + + + Scene location : Aliased path + + + + Scene location : Full path + + + + Output location : Aliased path + + + + Output location : Full path + + + + Image + + + + + BoardView + + Please set the duration more than 0 frame first, or the clapperboard settings will not be saved in the scene at all! + + + + BrightnessAndContrastPopup Brightness and Contrast @@ -2227,6 +2313,25 @@ contain the dpi information, then the current camera dpi will be used. Drag to Extend Onion Skin, Double Click to Toggle All + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + Click to Move Shift & Trace Marker + + FilmstripFrames @@ -2494,6 +2599,76 @@ Vuoi sovrascriverlo? + ItemInfoView + + Bold + + + + Italic + + + + Ignore + + + + Keep + + + + Name: + Nome: + + + Type: + Tipo: + + + Path: + Percorso: + + + Aspect Ratio: + + + + Font: + + + + Max Size: + + + + No item selected. + + + + Item + + + + + ItemListView + + Add + Aggiungi + + + Remove + Rimuovi + + + Move Up + + + + Move Down + + + + LayerFooterPanel Zoom in/out of timeline @@ -2990,6 +3165,13 @@ Please use the frame numbers for reference. + LoadBoardPresetFilePopup + + Load Clapperboard Settings Preset + + + + LoadColorModelPopup Load Color Model @@ -5093,10 +5275,6 @@ Decrementa lo spessore minimo del pennello - Flip Viewer Horiontally - - - Flip Viewer Vertically @@ -5156,6 +5334,50 @@ Decrementa lo spessore minimo del pennello Active Axis - All + + &Timeline + + + + Linear Interpolation + + + + Speed In / Speed Out Interpolation + + + + Ease In / Ease Out Interpolation + + + + Ease In / Ease Out (%) Interpolation + + + + Exponential Interpolation + + + + Expression Interpolation + + + + File Interpolation + + + + Constant Interpolation + + + + Separate Colors... + + + + Flip Viewer Horizontally + + MatchlinesDialog @@ -5729,6 +5951,25 @@ Cosa vuoi fare? Render + + Add Clapperboard + + + + Edit Clapperboard... + + + + Save current output settings. +The parameters to be saved are: +- Camera settings +- Project folder to be saved in +- File format +- File options +- Resample Balance +- Channel width + + OverwriteDialog @@ -7075,10 +7316,6 @@ if both are possible on coding file path. - Weight *: - - - OpenToonz can use FFmpeg for additional file formats. @@ -7181,6 +7418,55 @@ Also the initial output destination for new scenes will be set to $scenefolder a Compact + + Saving + + + + Use Onion Skin Colors for Reference Drawings of Shift and Trace + + + + Tablet Settings + + + + Enable Windows Ink Support* (EXPERIMENTAL) + + + + Constant + + + + Exponential + + + + Expression + + + + File + File + + + Style *: + + + + Matte color is used for background when overwriting raster levels with transparent pixels +in non alpha-enabled image format. + + + + Matte color: + + + + Current Column Color: + + PreferencesPopup::FormatProperties @@ -8050,7 +8336,7 @@ Alcuni livelli potrebbero non essere stati caricati perché la loro versione non The Revert to Last Saved command is not supported for the current selection. - Il comando Ricarica l'Ultima Versione Salvata non è disponibile per la selezione corrente. + Il comando Ricarica l'Ultima Versione Salvata non è disponibile per la selezione corrente. The selected column is empty. @@ -9017,6 +9303,67 @@ Allow duplicate? Nothing to replace: no cells or columns selected. + + Couldn't load %1 + + + + Apply Antialias + Applica Antialias + + + The Reload command is not supported for the current selection. + + + + Error + + + + No Palette loaded. + + + + A separation task is in progress! wait until it stops or cancel it + + + + Duplicate Frame in XSheet + + + + Please enable "Sync Level Strip Drawing Number Changes with the XSheet" preference option +to use the duplicate command in the xsheet / timeline. + + + + Please select only one layer to duplicate a frame. + + + + Please select only one frame to duplicate. + + + + Timeline + + + + The qualifier %1 is not a valid key name. Skipping. + + + + Clear All Onion Skin Markers + + + + Clear All Fixed Onion Skin Markers + + + + Clear All Relative Onion Skin Markers + + ReframePopup @@ -10004,6 +10351,13 @@ Per favore sottometti o ripristina i cambiamenti prima di proseguire. + SaveBoardPresetFilePopup + + Save Clapperboard Settings As Preset + + + + SaveCurvePopup Save Curve @@ -10398,6 +10752,172 @@ Per favore sottometti o ripristina i cambiamenti prima di proseguire. + SeparateColorsPopup + + Auto + Auto + + + Preview + Anteprima + + + Separate + + + + Close + Chiudi + + + Sub Color 3: + + + + Alpha Matting + + + + Main + + + + Sub1 + + + + Sub2 + + + + Sub3 + + + + Pick Color + + + + Show Mask + + + + Show Alpha + + + + Preview Frame: + + + + Paper Color: + + + + Main Color: + + + + Sub Color 1: + + + + Sub Color 2: + + + + Sub Adjust: + + + + Border Smooth: + + + + Mask Threshold: + + + + Mask Radius: + + + + Start: + Inizio: + + + End: + Fine: + + + Format: + Formato: + + + Save in: + + + + File Suffix: + + + + Cancel + Annullare + + + Separate by colors ... + + + + Separate 1 Level + + + + Separate %1 Levels + + + + Critical + + + + Failed to access the destination folder! + + + + Separating %1 + + + + Converting level %1 of %2: %3 + Converti %1 livelli di %2: %3 + + + + SeparateSwatch + + Sub Color 3 + + + + Original + + + + Main Color + + + + Sub Color 1 + + + + Sub Color 2 + + + + ShortcutPopup Configure Shortcuts @@ -11727,6 +12247,10 @@ Per favore fai riferimento alla Guida utente per i dettagli. Filter: + + Opacity: + + XsheetGUI::NoteArea @@ -11746,6 +12270,22 @@ Per favore fai riferimento alla Guida utente per i dettagli. 3sec Sheet + + Toggle Xsheet/Timeline + + + + Add New Memo + + + + Previous Memo + + + + Next Memo + + XsheetGUI::NotePopup @@ -11816,6 +12356,32 @@ Per favore fai riferimento alla Guida utente per i dettagli. Set Auto Markers + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + Click to Move Shift & Trace Marker + + + + + XsheetGUI::SoundColumnPopup + + Volume: + + XsheetGUI::XSheetToolbar diff --git a/toonz/sources/translations/italian/toonzqt.ts b/toonz/sources/translations/italian/toonzqt.ts index 23d7440..eba0a53 100644 --- a/toonz/sources/translations/italian/toonzqt.ts +++ b/toonz/sources/translations/italian/toonzqt.ts @@ -256,7 +256,7 @@ E' possibile che il file sia corrotto. &Open Subxsheet - &Apri il Sub-xsheet + &Apri il Sub-xsheet @@ -697,6 +697,17 @@ E' possibile che il file sia corrotto. + FontParamField + + Style: + + + + Size: + + + + FrameNavigator Previous Frame @@ -1086,7 +1097,7 @@ E' possibile che il file sia corrotto. &Open Subxsheet - &Apri il Sub-xsheet + &Apri il Sub-xsheet &Uncache Fx @@ -1202,6 +1213,13 @@ E' possibile che il file sia corrotto. + FxSchematicOutputNode + + Output + + + + FxSchematicPort &Disconnect from Xsheet @@ -1234,6 +1252,13 @@ Seleziona i nodi Effetto ed i relativi collegamenti prima di copiare o tagliare + FxSchematicXSheetNode + + XSheet + + + + FxSettings &Camera Preview @@ -2163,6 +2188,10 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< &Swtich output port display mode + + &Toggle node icons + + SchematicWindowEditor diff --git a/toonz/sources/translations/japanese/image.ts b/toonz/sources/translations/japanese/image.ts index fb57b98..324b9a4 100644 --- a/toonz/sources/translations/japanese/image.ts +++ b/toonz/sources/translations/japanese/image.ts @@ -4,12 +4,12 @@ AviWriterProperties - + Codec コーデック - + Uncompressed 非圧縮 @@ -69,52 +69,52 @@ Please try raising the FFmpeg timeout in Preferences. SgiWriterProperties - + Bits Per Pixel 色深度 - + 24 bits 24ビット - + 32 bits 32ビット - + 48 bits 48ビット - + 64 bits 64ビット - + 8 bits (Greyscale) 8ビット (グレースケール) - + Endianess エンディアン - + Big Endian ビッグエンディアン - + Little Endian リトルエンディアン - + RLE-Compressed RLE圧縮 @@ -180,37 +180,37 @@ Please try raising the FFmpeg timeout in Preferences. SvgWriterProperties - + Stroke Mode モード - + Outline Quality アウトラインの品質 - + Centerline 中心線 - + Outline アウトライン - + High - + Medium - + Low @@ -339,12 +339,12 @@ Please try raising the FFmpeg timeout in Preferences. WebmWriterProperties - + Quality 品質 - + Scale スケール(%) diff --git a/toonz/sources/translations/japanese/tnztools.ts b/toonz/sources/translations/japanese/tnztools.ts index d8d019a..8681364 100644 --- a/toonz/sources/translations/japanese/tnztools.ts +++ b/toonz/sources/translations/japanese/tnztools.ts @@ -96,7 +96,7 @@ Hardness: - 硬さ: + 硬さ: Accuracy: @@ -144,7 +144,7 @@ Pencil - 鉛筆モード + 鉛筆モード Pressure @@ -224,19 +224,19 @@ Draw Order: - 線の重ね順: + 線の重ね順: Over All - 上に描く + 上に描く Under All - 下に描く + 下に描く Palette Order - パレット順 + パレット順 @@ -1341,6 +1341,33 @@ Do you want to proceed? Link 縦横比を固定 + + Scale + 拡大率 + + + Position + 位置 + + + + ShiftTraceToolOptionBox + + Reset Previous + 前のコマの変形をリセット + + + Reset Following + 後のコマの変形をリセット + + + Previous Drawing + 前のコマ + + + Following Drawing + 後のコマ + SkeletonTool @@ -1422,6 +1449,53 @@ moved to the end of the first page of the palette. + ToonzRasterBrushTool + + Size + サイズ + + + Hardness: + 硬さ: + + + Smooth: + 平滑化: + + + Draw Order: + 線の重ね順: + + + Over All + 上に描く + + + Under All + 下に描く + + + Palette Order + パレット順 + + + Preset: + プリセット: + + + <custom> + <カスタム> + + + Pencil + 鉛筆モード + + + Pressure + 圧力感知 + + + TrackerTool Width: diff --git a/toonz/sources/translations/japanese/toonz.ts b/toonz/sources/translations/japanese/toonz.ts index 50ea896..0731fbc 100644 --- a/toonz/sources/translations/japanese/toonz.ts +++ b/toonz/sources/translations/japanese/toonz.ts @@ -367,6 +367,92 @@ Stop it or wait for its completion before removing it. + BoardSettingsPopup + + Clapperboard Settings + カットボールド設定 + + + Load Preset + プリセットを読み込む + + + Save as Preset + プリセットとして保存 + + + Close + 閉じる + + + Duration (frames): + 時間(フレーム): + + + Text + テキスト + + + Project name + プロジェクト名 + + + Scene name + シーン名 + + + Duration : Frame + カットの尺:フレーム + + + Duration : Sec + Frame + カットの尺:秒+コマ + + + Duration : HH:MM:SS:FF + カットの尺:時:分:秒:コマ + + + Current date + 日付 + + + Current date and time + 日付と時刻 + + + User name + ユーザー名 + + + Scene location : Aliased path + シーンファイルのパス:エイリアス + + + Scene location : Full path + シーンファイルのパス:フルパス + + + Output location : Aliased path + 出力ファイルのパス:エイリアス + + + Output location : Full path + 出力ファイルのパス:フルパス + + + Image + 画像 + + + + BoardView + + Please set the duration more than 0 frame first, or the clapperboard settings will not be saved in the scene at all! + カットボールドを有効にするには、まず時間(フレーム)を1以上に設定してください。0が設定されている場合カットボールド設定はシーンファイルに保存されません! + + + BrightnessAndContrastPopup Brightness and Contrast @@ -2226,6 +2312,28 @@ contain the dpi information, then the current camera dpi will be used. Drag to Extend Onion Skin, Double Click to Toggle All [ドラッグ] オニオンスキン範囲を設定 [ダブルクリック] 全フレーム切り替え + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + [クリック] ライトテーブルマーカーを隣接するフレームにリセット +[ビューア上でF2キー] このフレームのみ表示する + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + [クリック] このフレームをライトテーブルから除く +[ビューア上でF1キー] このフレームのみ表示する + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + [クリック] このフレームをライトテーブルから除く +[ビューア上でF3キー] このフレームのみ表示する + + + Click to Move Shift & Trace Marker + [クリック] ライトテーブルマーカーを移動 + FilmstripFrames @@ -2492,6 +2600,76 @@ Do you want to overwrite it? + ItemInfoView + + Bold + 太字 + + + Italic + 斜体 + + + Ignore + 無視する + + + Keep + 維持する + + + Name: + 名前: + + + Type: + タイプ: + + + Path: + パス: + + + Aspect Ratio: + 縦横比: + + + Font: + フォント: + + + Max Size: + 最大サイズ: + + + No item selected. + 項目が選択されていません。 + + + Item + 項目 + + + + ItemListView + + Add + 追加 + + + Remove + 削除 + + + Move Up + 上に移動 + + + Move Down + 下に移動 + + + LayerFooterPanel Zoom in/out of timeline @@ -2994,6 +3172,13 @@ Please use the frame numbers for reference. + LoadBoardPresetFilePopup + + Load Clapperboard Settings Preset + カットボールド設定のプリセットを読み込む + + + LoadColorModelPopup Load Color Model @@ -5113,7 +5298,7 @@ Please use the frame numbers for reference. Flip Viewer Horiontally - ビューアを水平方向に反転 + ビューアを水平方向に反転 Flip Viewer Vertically @@ -5167,6 +5352,50 @@ Please use the frame numbers for reference. Active Axis - All 編集ツール - 軸 - 全て + + &Timeline + タイムライン (&T) + + + Linear Interpolation + 線形 + + + Speed In / Speed Out Interpolation + スピードイン/スピードアウト + + + Ease In / Ease Out Interpolation + スローイン/スローアウト + + + Ease In / Ease Out (%) Interpolation + スローイン/スローアウト (%) + + + Exponential Interpolation + 指数関数 + + + Expression Interpolation + エクスプレッション + + + File Interpolation + ファイル + + + Constant Interpolation + 定数 + + + Separate Colors... + 色線を分ける... + + + Flip Viewer Horizontally + ビューアを水平方向に反転 + MatchlinesDialog @@ -5746,6 +5975,32 @@ What do you want to do? Render レンダリング + + Add Clapperboard + カットボールドを追加する + + + Edit Clapperboard... + カットボールドを編集... + + + Save current output settings. +The parameters to be saved are: +- Camera settings +- Project folder to be saved in +- File format +- File options +- Resample Balance +- Channel width + 現在の出力設定を保存します。 +プリセットには以下の値が保存されます: +- カメラ設定 +- 保存先となるプロジェクトフォルダ +- ファイル拡張子 +- ファイル形式オプション +- 画像補間方式 +- チャンネル幅 + OverwriteDialog @@ -7201,7 +7456,7 @@ if both are possible on coding file path. Weight *: - 文字の太さ *: + 文字の太さ *: OpenToonz can use FFmpeg for additional file formats. @@ -7309,6 +7564,56 @@ Also the initial output destination for new scenes will be set to $scenefolder a Compact コンパクト + + Saving + 保存 + + + Use Onion Skin Colors for Reference Drawings of Shift and Trace + ライトテーブルの前後フレームにもオニオンスキンの色を用いる + + + Tablet Settings + タブレット + + + Enable Windows Ink Support* (EXPERIMENTAL) + Windows Inkを用いる* (試験運用中の機能です) + + + Constant + 定数 + + + Exponential + 指数関数 + + + Expression + エクスプレッション + + + File + ファイル + + + Style *: + スタイル *: + + + Matte color is used for background when overwriting raster levels with transparent pixels +in non alpha-enabled image format. + マット色は、透明なピクセルを含む画像を、アルファチャンネル非対応のファイル形式で +上書き保存するときの背景に用いられます。 + + + Matte color: + マット色: + + + Current Column Color: + 現在の列の文字色: + PreferencesPopup::FormatProperties @@ -8164,7 +8469,7 @@ Some levels have not been loaded because their version is not supported The Revert to Last Saved command is not supported for the current selection. - 「最後に保存されたバージョンに戻す」コマンドは、現在の選択範囲に対応していません。 + 「最後に保存されたバージョンに戻す」コマンドは、現在の選択範囲に対応していません。 The selected column is empty. @@ -9192,6 +9497,69 @@ Allow duplicate? Nothing to replace: no cells or columns selected. 置き換えることができません:選択されているコマまたは列がありません。 + + Couldn't load %1 + %1 を読み込めませんでした + + + Apply Antialias + アンチエイリアスを適用 + + + The Reload command is not supported for the current selection. + 「再読み込み」コマンドは、現在の選択範囲に対応していません。 + + + Error + エラー + + + No Palette loaded. + パレットが読み込まれていません。 + + + A separation task is in progress! wait until it stops or cancel it + 色線を分けるタスクの処理中です! 完了まで待つか、またはキャンセルして下さい + + + Duplicate Frame in XSheet + タイムシート内で動画を複製 + + + Please enable "Sync Level Strip Drawing Number Changes with the XSheet" preference option +to use the duplicate command in the xsheet / timeline. + タイムシート/タイムライン上で動画を複製コマンドを使用するには、 +環境設定 > タイムシート > 「レベルビューア上の動画番号の変更を、タイムシートに同期する」 +オプションを有効にしてください。 + + + Please select only one layer to duplicate a frame. + このコマンドは1つのコマだけ選択して使用して下さい。 + + + Please select only one frame to duplicate. + このコマンドは1つのコマだけ選択して使用して下さい。 + + + Timeline + タイムライン + + + The qualifier %1 is not a valid key name. Skipping. + 修飾子 %1 は有効なキー名ではありません。スキップします。 + + + Clear All Onion Skin Markers + 全てのオニオンスキンをクリア + + + Clear All Fixed Onion Skin Markers + 全ての固定オニオンスキンをクリア + + + Clear All Relative Onion Skin Markers + 全ての連結オニオンスキンをクリア + ReframePopup @@ -10184,6 +10552,13 @@ Please commit or revert changes first. + SaveBoardPresetFilePopup + + Save Clapperboard Settings As Preset + 現在のカットボールド設定をプリセットに保存 + + + SaveCurvePopup Save Curve @@ -10590,6 +10965,172 @@ Please commit or revert changes first. + SeparateColorsPopup + + Auto + 自動更新 + + + Preview + プレビュー + + + Separate + 色分けを実行 + + + Close + 閉じる + + + Sub Color 3: + 色線 3 の色: + + + Alpha Matting + アルファマット + + + Main + 実線 + + + Sub1 + 色線1 + + + Sub2 + 色線2 + + + Sub3 + 色線3 + + + Pick Color + 色を拾う + + + Show Mask + マスク領域 + + + Show Alpha + アルファチャンネル + + + Preview Frame: + プレビューするフレーム: + + + Paper Color: + 紙の色: + + + Main Color: + 実線の色: + + + Sub Color 1: + 色線 1 の色: + + + Sub Color 2: + 色線 2 の色: + + + Sub Adjust: + 色線の強さ: + + + Border Smooth: + 境界をなじませる: + + + Mask Threshold: + しきい値: + + + Mask Radius: + マスクの半径: + + + Start: + 開始フレーム: + + + End: + 終了フレーム: + + + Format: + ファイル形式: + + + Save in: + 保存先: + + + File Suffix: + ファイル接尾子: + + + Cancel + キャンセル + + + Separate by colors ... + 色線を分ける ... + + + Separate 1 Level + レベル内の色線を分ける + + + Separate %1 Levels + %1 個のレベルの色線を分ける + + + Critical + 警告 + + + Failed to access the destination folder! + 保存先フォルダのアクセスに失敗しました! + + + Separating %1 + %1 の色分けを実行中 + + + Converting level %1 of %2: %3 + %1 / %2 レベルを変換中: %3 + + + + SeparateSwatch + + Sub Color 3 + 色線 3 + + + Original + 元画像 + + + Main Color + 実線 + + + Sub Color 1 + 色線 1 + + + Sub Color 2 + 色線 2 + + + ShortcutPopup Configure Shortcuts @@ -11970,6 +12511,10 @@ Please refer to the user guide for details. Filter: フィルタ: + + Opacity: + 不透明度: + XsheetGUI::NoteArea @@ -11989,6 +12534,22 @@ Please refer to the user guide for details. 3sec Sheet 3秒シート + + Toggle Xsheet/Timeline + タイムシート/タイムライン切り替え + + + Add New Memo + 新規メモを追加 + + + Previous Memo + 前のメモ + + + Next Memo + 次のメモ + XsheetGUI::NotePopup @@ -12063,6 +12624,35 @@ Please refer to the user guide for details. Set Auto Markers 素材の範囲にマーカーを自動設定 + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + [クリック] ライトテーブルマーカーを隣接するフレームにリセット +[ビューア上でF2キー] このフレームのみ表示する + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + [クリック] このフレームをライトテーブルから除く +[ビューア上でF1キー] このフレームのみ表示する + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + [クリック] このフレームをライトテーブルから除く +[ビューア上でF3キー] このフレームのみ表示する + + + Click to Move Shift & Trace Marker + [クリック] ライトテーブルマーカーを移動 + + + + XsheetGUI::SoundColumnPopup + + Volume: + 音量: + XsheetGUI::Toolbar diff --git a/toonz/sources/translations/japanese/toonzqt.ts b/toonz/sources/translations/japanese/toonzqt.ts index d1e9654..fe5bb06 100644 --- a/toonz/sources/translations/japanese/toonzqt.ts +++ b/toonz/sources/translations/japanese/toonzqt.ts @@ -256,7 +256,7 @@ Possibly the preset file has been corrupted &Open Subxsheet - サブシートを開く (&O) + サブシートを開く (&O) @@ -697,6 +697,17 @@ Possibly the preset file has been corrupted + FontParamField + + Style: + スタイル: + + + Size: + サイズ: + + + FrameNavigator Previous Frame @@ -1086,7 +1097,7 @@ Possibly the preset file has been corrupted &Open Subxsheet - サブシートを開く (&O) + サブシートを開く (&O) &Uncache Fx @@ -1206,6 +1217,13 @@ Possibly the preset file has been corrupted + FxSchematicOutputNode + + Output + 出力 + + + FxSchematicPort &Disconnect from Xsheet @@ -1238,6 +1256,13 @@ Select FX nodes and related links before copying or cutting the selection you wa + FxSchematicXSheetNode + + XSheet + タイムシート + + + FxSettings &Camera Preview @@ -2193,6 +2218,10 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< &Swtich output port display mode ポートの表示を切り替える (&S) + + &Toggle node icons + アイコン表示切り替え (&T) + SchematicWindowEditor diff --git a/toonz/sources/translations/korean/image.ts b/toonz/sources/translations/korean/image.ts index 73006fb..b08615c 100644 --- a/toonz/sources/translations/korean/image.ts +++ b/toonz/sources/translations/korean/image.ts @@ -4,12 +4,12 @@ AviWriterProperties - + Codec - + Uncompressed @@ -67,52 +67,52 @@ Please try raising the FFmpeg timeout in Preferences. SgiWriterProperties - + Bits Per Pixel - + 24 bits - + 32 bits - + 48 bits - + 64 bits - + 8 bits (Greyscale) - + Endianess - + Big Endian - + Little Endian - + RLE-Compressed @@ -178,37 +178,37 @@ Please try raising the FFmpeg timeout in Preferences. SvgWriterProperties - + Stroke Mode - + Outline Quality - + Centerline - + Outline - + High - + Medium - + Low @@ -337,12 +337,12 @@ Please try raising the FFmpeg timeout in Preferences. WebmWriterProperties - + Quality - + Scale diff --git a/toonz/sources/translations/korean/tnzcore.ts b/toonz/sources/translations/korean/tnzcore.ts index f7e45c0..71d5612 100644 --- a/toonz/sources/translations/korean/tnzcore.ts +++ b/toonz/sources/translations/korean/tnzcore.ts @@ -4,17 +4,17 @@ BmpWriterProperties - + Bits Per Pixel - + 24 bits - + 8 bits (Greyscale) @@ -22,12 +22,12 @@ JpgWriterProperties - + Quality - + Smoothing @@ -58,12 +58,12 @@ TCenterLineStrokeStyle - + Constant - + Thickness @@ -71,12 +71,12 @@ TRasterImagePatternStrokeStyle - + Distance - + Rotation @@ -84,12 +84,12 @@ TVectorImagePatternStrokeStyle - + Distance - + Rotation diff --git a/toonz/sources/translations/korean/tnztools.ts b/toonz/sources/translations/korean/tnztools.ts index 268f4e8..1e0921f 100644 --- a/toonz/sources/translations/korean/tnztools.ts +++ b/toonz/sources/translations/korean/tnztools.ts @@ -4,101 +4,101 @@ ArrowToolOptionsBox - + Z: - + Position: - - + + E/W: - - + + N/S: - + SO: - + Rotation: - + Global: - - + + H: - - + + V: - + Position - + ( - + ) - + Rotation - + Scale - + Maintain: - + Shear - + Center Position - + Table - + Pick: @@ -106,164 +106,133 @@ BrushTool - - + Size - - Hardness: - - - - + Accuracy: - + Smooth: - - Draw Order: - - - - - Over All - - - - - Under All - - - - - Palette Order - - - - + Preset: - - + + <custom> - + Break - - Pencil - - - - + Pressure - + Cap - + Join - + Miter: - + Range: - + Snap - + Off - + Linear - + In - + Out - + In&Out - + Low - + Med - + High - + Butt cap - + Round cap - + Projecting cap - + Miter join - + Round join - + Bevel join @@ -271,17 +240,17 @@ BrushToolOptionsBox - + Preset Name - + OK - + Cancel @@ -310,7 +279,7 @@ DVGui::StyleIndexLineEdit - + current @@ -480,85 +449,85 @@ EraserTool - + Size: - + Selective - + Invert - + Frame Range - + Type: - + Normal - + Rectangular - + Freehand - + Polyline - + Hardness: - + Mode: - + Lines - + Areas - + Lines & Areas - + Pencil Mode @@ -649,12 +618,12 @@ FingerTool - + Size: - + Invert @@ -699,7 +668,7 @@ - + <custom> @@ -707,52 +676,52 @@ FullColorEraserTool - + Size: - + Opacity: - + Hardness: - + Type: - + Normal - + Rectangular - + Freehand - + Polyline - + Invert - + Frame Range @@ -776,32 +745,32 @@ PaintBrushTool - + Size: - + Mode: - + Lines - + Areas - + Lines & Areas - + Selective @@ -809,17 +778,17 @@ PinchTool - + Size: - + Corner: - + Manual @@ -827,22 +796,22 @@ PlasticTool - + Swap Edge - + Collapse Edge - + Split Edge - + Cut Mesh @@ -942,54 +911,54 @@ - + A group of skeletons already exists for current column. Replacing it will also substitute any existing vertex animation. Do you want to continue? - + Ok - + Cancel - + Copy Skeleton - + Paste Skeleton - + Show Mesh - + Show Rigidity - + Show SO - + Show Skeleton Onion Skin - + The previous vertex name will be discarded, and all associated keys will be lost. Do you want to proceed? @@ -1194,25 +1163,25 @@ Do you want to proceed? QObject - + The copied selection cannot be pasted in the current drawing. - - + + Paste - - + + Min: - - + + Max: @@ -1232,12 +1201,12 @@ Do you want to proceed? - + Ok - + Cancel @@ -1277,19 +1246,19 @@ Do you want to proceed? + - Yes + - No - + Modify Fx Gadget @@ -1432,7 +1401,7 @@ Do you want to proceed? RGBPickerToolOptionsBox - + Pick Screen @@ -1519,37 +1488,37 @@ Do you want to proceed? RulerToolOptionsBox - + X: ruler tool option - + Y: ruler tool option - + W: ruler tool option - + H: ruler tool option - + A: ruler tool option - + L: ruler tool option @@ -1581,42 +1550,76 @@ Do you want to proceed? SelectionToolOptionsBox - + H: - + V: - + Link - + + Rotation - + E/W: - + N/S: - + + Scale + + + + + Position + + + + Thickness + ShiftTraceToolOptionBox + + + Reset Previous + + + + + Reset Following + + + + + Previous Drawing + + + + + Following Drawing + + + + SkeletonTool @@ -1705,13 +1708,73 @@ Do you want to proceed? StylePickerToolOptionsBox - + With this option being activated, the picked style will be moved to the end of the first page of the palette. + ToonzRasterBrushTool + + + + Size + + + + + Hardness: + + + + + Smooth: + + + + + Draw Order: + + + + + Over All + + + + + Under All + + + + + Palette Order + + + + + Preset: + + + + + + <custom> + + + + + Pencil + + + + + Pressure + + + + TrackerTool @@ -1737,22 +1800,22 @@ moved to the end of the first page of the palette. TypeTool - + Font: - + Style: - + Vertical Orientation - + Size: diff --git a/toonz/sources/translations/korean/toonz.ts b/toonz/sources/translations/korean/toonz.ts index 78b8a59..51bb25f 100644 --- a/toonz/sources/translations/korean/toonz.ts +++ b/toonz/sources/translations/korean/toonz.ts @@ -144,28 +144,28 @@ AudioRecordingPopup - + Audio Recording - + Save and Insert - + Sync with XSheet - - + + - + The microphone is not available: Please select a different device or check the microphone. @@ -446,6 +446,112 @@ Do you want to save your changes? + BoardSettingsPopup + + + Clapperboard Settings + + + + + Load Preset + + + + + Save as Preset + + + + + Close + + + + + Duration (frames): + + + + + Text + + + + + Project name + + + + + Scene name + + + + + Duration : Frame + + + + + Duration : Sec + Frame + + + + + Duration : HH:MM:SS:FF + + + + + Current date + + + + + Current date and time + + + + + User name + + + + + Scene location : Aliased path + + + + + Scene location : Full path + + + + + Output location : Aliased path + + + + + Output location : Full path + + + + + Image + + + + + BoardView + + + Please set the duration more than 0 frame first, or the clapperboard settings will not be saved in the scene at all! + + + + BrightnessAndContrastPopup @@ -710,27 +816,27 @@ Do you want to crop the canvas? CastBrowser - + It is not possible to edit the selected file. - + It is not possible to edit more than one file at once. - + It is not possible to show the folder containing the selected file, as the file has not been saved yet. - + It is not possible to view the selected file, as the file has not been saved yet. - + It is not possible to show the info of the selected file, as the file has not been saved yet. @@ -738,17 +844,17 @@ Do you want to crop the canvas? CastTreeViewer - + Delete folder - + Yes - + No @@ -1169,12 +1275,12 @@ What do you want to do? CloneLevelUndo::LevelNamePopup - + Clone Level - + Level Name: @@ -1304,94 +1410,94 @@ What do you want to do? ComboViewerPanel - + GUI Show / Hide - + Toolbar - + Tool Options Bar - + Console - + Safe Area (Right Click to Select) - + Field Guide - + Camera Stand View - + 3D View - + Camera View - + Freeze - + Preview - + Sub-camera Preview - + Untitled - + Scene: - + :: Frame: - - - + + + (Flipped) - + :: Level: - + Level: @@ -1487,185 +1593,185 @@ What do you want to do? ConvertPopup - + Level %1 already exists; skipped. - + Converting %1 - + Converting level %1 of %2: %3 - + Level %1 has no frame; skipped. - + Unpainted tlv - + Unpainted tlv from non AA source - + Painted tlv from two images - + Painted tlv from non AA source - - + + Same as Painted - + Create new palette - + Options - + Convert - - - + + + Cancel - + Bg Color: - + Skip Existing Files - + Remove dot before frame number - + Convert... - + File to convert: - + Start: - + End: - + Save in: - + File Name: - + File Format: - + Stroke Mode: - + Centerline - + Outline - + Unpainted File Folder: - + Unpainted File Suffix: - + Apply Autoclose - + Save Backup to "nopaint" Folder - + Append Default Palette - + Remove Unused Styles from Input Palette - + Keep Original Antialiasing - + Add Antialiasing with Intensity: - + Remove Antialiasing using Threshold: - + When activated, styles of the default palette ($TOONZSTUDIOPALETTE\cleanup_default.tpl) will be appended to the palette after conversion in @@ -1674,22 +1780,22 @@ before color designing. - + Image DPI - + Current Camera DPI - + Custom DPI - + Specify the policy for setting DPI of converted tlv. If you select the "Image DPI" option and the source image does not contain the dpi information, then the current camera dpi will be used. @@ -1697,103 +1803,103 @@ contain the dpi information, then the current camera dpi will be used. - + Mode: - + Antialias: - + Palette: - + Tolerance: - + Dpi: - + Convert 1 Level - + Convert %1 Levels - - + + Level - + already exists; skipped - + Generating level - + converted to tlv. - + Level %1 converted to TLV Format - + Warning: Level %1 NOT converted to TLV Format - + Converted %1 out of %2 Levels to TLV Format - + Warning: Can't read palette '%1' - + No output filename specified: please choose a valid level name. - + No unpainted suffix specified: cannot convert. - + Convert completed with %1 error(s) and %2 level(s) skipped - + Convert completed with %1 error(s) - + %1 level(s) skipped @@ -1801,7 +1907,7 @@ contain the dpi information, then the current camera dpi will be used. DVGui::ProgressDialog - + Loading "%1"... @@ -2069,12 +2175,12 @@ contain the dpi information, then the current camera dpi will be used. ExportCurvePopup - + Export Curve - + Export @@ -2319,206 +2425,206 @@ contain the dpi information, then the current camera dpi will be used. - + Folder: - + Open folder failed - + The input folder path was invalid. - + Can't change file extension - + Can't set a drawing number - + Can't rename. File already exists: - + Couldn't rename - + Preview Screensaver - + Install Screensaver - + Load As Sub-xsheet - + Load - + Rename - + Convert to Painted TLV - + Convert to Unpainted TLV - + Version Control - - + + Edit - - + + Edit Frame Range... - - - + + + Put... - - + + Revert - - - - - + + + + + Get - + Delete - + Get Revision... - + Unlock - - - + + + Edit Info - + Revision History... - + Unlock Frame Range - + Save Scene - + Scene name: - + There was an error copying %1 to %2 - + Convert To Unpainted Tlv - - + + Warning: level %1 already exists; overwrite? - - + + Yes - - + + No - + Done: All Levels converted to TLV Format - + Convert To Painted Tlv - + Done: 2 Levels converted to TLV Format - + New Folder - + It is not possible to create the %1 folder. @@ -2574,18 +2680,18 @@ contain the dpi information, then the current camera dpi will be used. FileSelection - + Collecting assets... - - + + Abort - + Importing scenes... @@ -2606,20 +2712,20 @@ contain the dpi information, then the current camera dpi will be used. Filmstrip - - - - + + + + - No Current Level - - + Level Strip - + Level: @@ -2627,30 +2733,53 @@ contain the dpi information, then the current camera dpi will be used. FilmstripFrameHeadGadget - + Click to Toggle Fixed Onion Skin - + Click / Drag to Toggle Onion Skin - + Drag to Extend Onion Skin, Double Click to Toggle All + + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + + Click to Move Shift & Trace Marker + + FilmstripFrames - + no icon - + Linear @@ -2658,55 +2787,55 @@ contain the dpi information, then the current camera dpi will be used. FlipBook - - + + Flipbook - + The file name cannot be empty or contain any of the following characters:(new line) \ / : * ? " | - + It is not possible to save because the selected file format is not supported. - + File %1 already exists. Do you want to overwrite it? - + It is not possible to save Flipbook content. - + Saved %1 frames out of %2 in %3 - + There are no rendered images to save. - - + + It is not possible to take or compare snapshots for Toonz vector levels. - + Rendered Frames :: From %1 To %2 :: Step %3 - + :: Shrink @@ -2714,12 +2843,12 @@ Do you want to overwrite it? FlipbookPanel - + Safe Area (Right Click to Select) - + Minimize @@ -2740,12 +2869,12 @@ Do you want to overwrite it? FrameHeadGadget - + Current Frame - + Fixed Onion Skin Toggle @@ -2860,38 +2989,38 @@ Do you want to overwrite it? InbetweenDialog - - + + Inbetween - + Linear - + Ease In - + Ease Out - + Ease In / Ease Out - + Interpolation: - + Cancel @@ -2955,6 +3084,92 @@ Do you want to overwrite it? + ItemInfoView + + + Bold + + + + + Italic + + + + + Ignore + + + + + Keep + + + + + Name: + + + + + Type: + + + + + Path: + + + + + Aspect Ratio: + + + + + Font: + + + + + Max Size: + + + + + No item selected. + + + + + Item + + + + + ItemListView + + + Add + + + + + Remove + + + + + Move Up + + + + + Move Down + + + + LayerFooterPanel @@ -2975,17 +3190,17 @@ Do you want to overwrite it? LayerHeaderPanel - + Preview Visbility Toggle All - + Camera Stand Visibility Toggle All - + Lock Toggle All @@ -3123,158 +3338,158 @@ Do you want to create it? LevelSettingsPopup - - + + DPI: - - + + Premultiply - - + + White As Transparent - - + + Add Antialiasing - - + + Antialias Softness: - - + + Subsampling: - + Level Settings - + Scan Path: - + Forced Squared Pixel - + Width: - + Height: - + Use Camera DPI - + Camera DPI: - + Image DPI: - + Resolution: - + Image DPI - + Custom DPI - + Name && Path - + Name: - + Path: - + Resolution - + DPI && Resolution - + Scan level - + Toonz Vector level - + Toonz Raster level - + Raster level - + Mesh level - + Palette level - + Sound Column - + The file %1 is not a sound level. @@ -3385,32 +3600,32 @@ Do you want to create it? LineTestPane - + Preview - + Untitled - + Scene: - + :: Frame: - + :: Level: - + Level: @@ -3554,6 +3769,14 @@ Please use the frame numbers for reference. + LoadBoardPresetFilePopup + + + Load Clapperboard Settings Preset + + + + LoadColorModelPopup @@ -3574,12 +3797,12 @@ Please use the frame numbers for reference. LoadCurvePopup - + Load Curve - + Load @@ -3595,42 +3818,42 @@ Please use the frame numbers for reference. LoadImagesPopup - + Load Images - + Append - + From: - + To: - + Step: - + Shrink: - + Load - + Load / Append Images @@ -3911,2088 +4134,2138 @@ Please use the frame numbers for reference. - + Cleanup - + PltEdit - + InknPaint - + Xsheet - + About OpenToonz - + Close - + Cannot delete - + &New Scene - + &Load Scene... - + &Save Scene - + &Save Scene As... - + &Save All - + &Revert Scene - + &Load Folder... - + &Load As Sub-xsheet... - + &Open Recent Scene File - + &Open Recent Level File - + &Clear Recent Scene File List - + &Clear Recent level File List - + &New Level... - + &New Vector Level - + New Vector Level - + &New Toonz Raster Level - + New Toonz Raster Level - + &New Raster Level - + New Raster Level - + &Load Level... - + &Save Level - + &Save All Levels - + &Save Level As... - + &Export Level... - + &Convert File... - + &Save Palette As... - + &Save Palette - + &Load Color Model... - + &Import Magpie File... - + &New Project... - + &Project Settings... - + &Save Default Settings - + &Output Settings... - + &Preview Settings... - + &Render - + &Fast Render to MP4 - + &Preview - + &Export Soundtrack - + &Save Previewed Frames - + &Regenerate Preview - + &Regenerate Frame Preview - + &Clone Preview - + &Freeze//Unfreeze Preview - + Freeze Preview - + Unfreeze Preview - + &Save As Preset - + &Preferences... - + &Configure Shortcuts... - + &Print Xsheet - + Run Script... - + Open Script Console... - + &Print Current Frame... - + &Quit - + Reload qss - + &Load Recent Image Files - + &Clear Recent Flipbook Image List - + Preview Fx - + &Select All - + &Invert Selection - + &Undo - + &Redo - + &Cut - + &Copy - + &Paste Insert - + &Paste Insert Above/After - + &Merge - + &Paste Into - + &Paste Color && Name - + Paste Color - + Paste Name - + Get Color from Studio Palette - + Toggle Link to Studio Palette - + Remove Reference to Studio Palette - + &Delete - + &Insert - + &Insert Above/After - + &Group - + &Ungroup - + &Bring to Front - + &Bring Forward - + &Send Back - + &Send Backward - + &Enter Group - + &Exit Group - + &Remove Vector Overflow - + &Touch Gesture Control - + &Define Scanner... - + &Scan Settings... - + &Scan - + &Autocenter... - + &Set Cropbox - + &Reset Cropbox - + &Cleanup Settings... - + &Preview Cleanup - + &Camera Test - + &Opacity Check - + &Cleanup - + &Camera Capture... - + &Add Frames... - + &Renumber... - + &Replace Level... - + &Revert to Cleaned Up - + &Reload - + &Expose in Xsheet - + &Display in Level Strip - + &Level Settings... - + Adjust Levels... - + Adjust Thickness... - + &Antialias... - + &Binarize... - + &Brightness and Contrast... - + &Color Fade... - + &Capture - + &Canvas Size... - + &Info... - + &View... - + &Remove All Unused Levels - + &Replace Parent Directory... - + &Scene Settings... - - + + &Camera Settings... - + &Open Sub-xsheet - + &Close Sub-xsheet - + Explode Sub-xsheet - + Collapse - + &Toggle Edit In Place - + Toggle Edit in Place - + &Save Sub-xsheet As... - + Resequence - + Clone Sub-xsheet - + &Apply Match Lines... - + &Merge Tlv Levels... - + &Delete Match Lines - + &Delete Lines... - + &Merge Levels - + &New FX... - + &New Output - + &Edit FX... - + Insert Frame - + Remove Frame - + Insert Multiple Keys - + Remove Multiple Keys - + New Note Level - + Remove Empty Columns - + &Apply Lip Sync Data to Column - + Toggle XSheet Toolbar - + &Reverse - + &Swing - + &Random - + &Autoexpose - + &Repeat... - + &Reset Step - + &Increase Step - + &Decrease Step - + &Step 2 - + &Step 3 - + &Step 4 - + &Each 2 - + &Each 3 - + &Each 4 - + &Roll Up - + &Roll Down - + &Time Stretch... - + &Duplicate Drawing - + &Autorenumber - + &Clone - + Drawing Substitution Forward - + Drawing Substitution Backward - + Similar Drawing Substitution Forward - + Similar Drawing Substitution Backward - + 1's - + 2's - + 3's - + 4's - + Reframe with Empty Inbetweens... - + Auto Input Cell Number... - + &Fill In Empty Cells - + &Set Key - + &Paste Numbers - + &Camera Box - + &Table - + &Field Guide - + &Raster Bounding Box - + &Field Guide in Capture Window - + &Safe Area - + &Camera BG Color - + &Guide - + &Ruler - + &Transparency Check - + &Ink Check - + &Ink#1 Check - + &Paint Check - + Inks &Only - + &Fill Check - + &Black BG Check - + &Gap Check - + Shift and Trace - + Edit Shift - + No Shift - + Reset Shift - + &Visualize Vector As Raster - + &Histogram - + Link Flipbooks - + Play - + Loop - + Pause - + First Frame - + Last Frame - + Previous Frame - + Next Frame - + Next Drawing - + Prev Drawing - + Next Step - + Prev Step - + Red Channel - + Green Channel - + Blue Channel - + Alpha Channel - + Red Channel Greyscale - + Green Channel Greyscale - + Blue Channel Greyscale - + Compare to Snapshot - + Toggle Autofill on Current Palette Color - + &Lock Room Panes - + &Export - + &File Browser - + &Flipbook - + &Function Editor - + &Level Strip - + &Palette - + &Palette Gizmo - + &Delete Unused Styles - + &Tasks - + &Batch Servers - + &Message Center - + &Color Model - + &Studio Palette - + &Schematic - + &Cleanup Settings - + &Scene Cast - + &Style Editor - + &Toolbar - + &Tool Option Bar - + &Command Bar - + &Viewer - + &LineTest Capture - + &LineTest Viewer - + &Xsheet - + + &Timeline + + + + &ComboViewer - + &History - + Record Audio - + &Reset to Default Rooms - + Toggle Maximize Panel - + Toggle Main Window's Full Screen Mode - + &About OpenToonz... - + &Startup Popup... - + &Blend colors - + Onion Skin Toggle - + Zero Thick Lines - + Toggle Cursor Size Outline - + Toggle Current Time Indicator - + Duplicate - + Show Folder Contents - + Convert... - + Collect Assets - + Import Scene - + Export Scene... - + Convert to Vectors... - + Vectors to Toonz Raster - + Replace Vectors with Simplified Vectors - + Tracking... - + Remove Level - + Add As Render Task - + Add As Cleanup Task - + Select All Keys in this Frame - + Select All Keys in this Column - + Select All Keys - + Select All Following Keys - + Select All Previous Keys - + Select Previous Keys in this Column - + Select Following Keys in this Column - + Select Previous Keys in this Frame - + Select Following Keys in this Frame - + Invert Key Selection - + Set Acceleration - + Set Deceleration - + Set Constant Speed - + Reset Interpolation - + + Linear Interpolation + + + + + Speed In / Speed Out Interpolation + + + + + Ease In / Ease Out Interpolation + + + + + Ease In / Ease Out (%) Interpolation + + + + + Exponential Interpolation + + + + + Expression Interpolation + + + + + File Interpolation + + + + + Constant Interpolation + + + + Fold Column - + Show This Only - + Show Selected - + Show All - + Hide Selected - + Hide All - + Toggle Show/Hide - + ON This Only - + ON Selected - + ON All - + OFF All - + OFF Selected - + Swap ON/OFF - + Lock This Only - + Lock Selected - + Lock All - + Unlock Selected - + Unlock All - + Swap Lock/Unlock - + Hide Upper Columns - + + Separate Colors... + + + + Animate Tool - + Selection Tool - + Brush Tool - + Geometric Tool - + Type Tool - + Fill Tool - + Paint Brush Tool - + Eraser Tool - + Tape Tool - + Style Picker Tool - + RGB Picker Tool - + Control Point Editor Tool - + Pinch Tool - + Pump Tool - + Magnet Tool - + Bender Tool - + Iron Tool - + Cutter Tool - + Skeleton Tool - + Tracker Tool - + Hook Tool - + Zoom Tool - + Rotate Tool - + Hand Tool - + Plastic Tool - + Ruler Tool - + Finger Tool - + Zoom In - + Zoom Out - + Reset View - + Fit to Window - + Actual Pixel Size - - Flip Viewer Horiontally + + Flip Viewer Horizontally - + Flip Viewer Vertically - + Show//Hide Full Screen - + Full Screen Mode - + Exit Full Screen Mode - + Refresh Folder Tree - + Refresh - + Global Key - + Brush size - Increase max - + Brush size - Decrease max - + Brush size - Increase min - + Brush size - Decrease min - + Brush hardness - Increase - + Brush hardness - Decrease - + SnapSensitivity - + Auto Group - + Break sharp angles - + Frame range - + Inverse kinematics - + Invert - + Manual - + Onion skin - + Orientation - + Pencil Mode - + Preserve Thickness - + Pressure Sensitivity - + Segment Ink - + Selective - + Brush Tool - Draw Order - + Smooth - + Snap - + Auto Select Drawing - + Auto Fill - + Join Vectors - + Show Only Active Skeleton - + Brush Preset - + Geometric Shape - + Geometric Edge - + Mode - + Mode - Areas - + Mode - Lines - + Mode - Lines & Areas - + Type - + Type - Normal - + Type - Rectangular - + Type - Freehand - + Type - Polyline - + TypeTool Font - + TypeTool Size - + TypeTool Style - + Active Axis - + Active Axis - Position - + Active Axis - Rotation - + Active Axis - Scale - + Active Axis - Shear - + Active Axis - Center - + Active Axis - All - + Build Skeleton Mode - + Animate Mode - + Inverse Kinematics Mode - + None Pick Mode - + Column Pick Mode - + Pegbar Pick Mode - + Pick Screen - + Create Mesh - + Fill Tool - Autopaint Lines - + Fill Tool - Areas - + Fill Tool - Lines - + Style Picker Tool - Areas - + Style Picker Tool - Lines - + Toggle FX/Stage schematic @@ -6200,63 +6473,63 @@ N.B. Duplicated commands will be ignored. Only the last one will appear in the m MeshifyPopup - + A level with the preferred path "%1" already exists. What do you want to do? - + Delete the old level entirely - + Keep the old level and overwrite processed frames - + Choose a different path (%1) - + Create Mesh - + Mesh Edges Length: - + Rasterization DPI: - + Mesh Margin (pixels): - + Apply - + Mesh Creation in progress... - + Current selection contains mixed image and mesh level types - + Current selection contains no image or mesh level types @@ -6298,7 +6571,7 @@ What do you want to do? MyViewFinder - + Camera is not available @@ -6306,341 +6579,363 @@ What do you want to do? OutputSettingsPopup - + Preview Settings - + Output Settings - + Camera Settings - + File Settings - + Options - + Use Sub-Camera - + Apply Shrink to Main Viewer - + Other Settings - + Render - + Add - + Remove - + Do stereoscopy - + Standard - + Improved - + High - + Triangle filter - + Mitchell-Netravali filter - + Cubic convolution, a = .5 - + Cubic convolution, a = .75 - + Cubic convolution, a = 1 - + Hann window, rad = 2 - + Hann window, rad = 3 - + Hamming window, rad = 2 - + Hamming window, rad = 3 - + Lanczos window, rad = 2 - + Lanczos window, rad = 3 - + Gaussian convolution - + Closest Pixel (Nearest Neighbor) - + Bilinear - + 8 bit - + + Add Clapperboard + + + + + Edit Clapperboard... + + + + 16 bit - + Odd (NTSC) - + Even (PAL) - - - + + + None - + Fx Schematic Flows - + Fx Schematic Terminal Nodes - + + Save current output settings. +The parameters to be saved are: +- Camera settings +- Project folder to be saved in +- File format +- File options +- Resample Balance +- Channel width + + + + Single - + Half - + All - + Large - + Medium - + Small - + Presets: - + Output Camera: - + Frame Start: - + End: - + Step: - + Shrink: - + Save in: - + Name: - + Resample Balance: - + Channel Width: - + Dedicated CPUs: - + Render Tile: - + Gamma: - + Dominant Field: - + Frame Rate (linked to Scene Settings): - + Stretch from FPS: - + To: - + Multiple Rendering: - + Camera Shift: - + Add preset - + Enter the name for the output settings preset. - + Add output settings preset - + <custom> - + Remove preset - - - + + + Warning @@ -6648,7 +6943,7 @@ What do you want to do? OverwriteDialog - + Level "%1" already exists. What do you want to do? @@ -6732,375 +7027,375 @@ Do you want to overwrite it? PencilTestPopup - + No frame id - + Camera Capture - + Refresh - + File - + Options - + Save images as they are captured - + Image adjust - + Upside down - + Capture white BG - + Display - + Show onion skin - + Load Selected Image - + Interval timer - + Use interval timer - - + + Capture [Return key] - + Close - + Subfolder - + Next Level - + Previous Level - + Color - + Grayscale - + Black & White - + Video Capture Filter Settings... - + Camera: - + Resolution: - + Save In: - + Name: - + Frame: - + File Type: - + Color type: - + BG reduction: - + Opacity(%): - + Interval(sec): - + No camera found - + - Select camera - - - + + No image selected. Please select an image in the Xsheet. - + The selected image is not in a raster level. - + The selected image size does not match the current camera settings. - - + + Start Capturing [Return key] - + Stop Capturing [Return key] - + No level name specified: please choose a valid level name - + Folder %1 doesn't exist. Do you want to create it? - + Unable to create - + The level name specified is already used: please choose a different level name. - + The save in path specified does not match with the existing level. - - + + The captured image size does not match with the existing level. - - + + File %1 does exist. Do you want to overwrite it? - + Failed to load %1. - - - - - + + + + + UNDEFINED WARNING - + The level is not registered in the scene, but exists in the file system. - + WARNING : Image size mismatch. The saved image size is %1 x %2. - - - - + + + + WARNING - - + + Frame %1 exists. - - + + Frames %1 exist. - - + + OVERWRITE 1 of - - + + ADD to - - + + %1 frame - - + + %1 frames - + The level will be newly created. - + NEW - + The level is already registered in the scene. - + NOTE : The level is not saved. - + WARNING : Failed to get image size of the existing level %1. - + WARNING : Image size mismatch. The existing level size is %1 x %2. - + WARNING : Level name conflicts. There already is a level %1 in the scene with the path %2. - + WARNING : Image size mismatch. The size of level with the same name is is %1 x %2. - + WARNING : Level path conflicts. There already is a level with the path %1 in the scene with the name %2. - + WARNING : Image size mismatch. The size of level with the same path is %1 x %2. @@ -7109,133 +7404,133 @@ WARNING : Image size mismatch. The size of level with the same path is %1 x %2.< PencilTestSaveInFolderPopup - + Create the Destination Subfolder to Save - + Set As Default - + Set the current "Save In" path as the default. - + Create Subfolder - + Infomation - + Subfolder Name - + Auto Format: - + Show This on Launch of the Camera Capture - + Save Scene in Subfolder - + OK - + Cancel - + C- + Sequence + Scene - + Sequence + Scene - + Episode + Sequence + Scene - + Project + Episode + Sequence + Scene - + Save the current scene in the subfolder. Set the output folder path to the subfolder as well. - + Save In: - + Project: - + Episode: - + Sequence: - + Scene: - + Subfolder Name: - + Subfolder name should not be empty. - + Subfolder name should not contain following characters: * . " / \ [ ] : ; | = , - + Folder %1 already exists. - + It is not possible to create the %1 folder. @@ -7243,67 +7538,67 @@ Set the output folder path to the subfolder as well. PltGizmoPopup - + Palette Gizmo - + Blend - + Fade - + Full Alpha - + Zero Alpha - + Scale (%) - + Shift (value) - + Value - + Saturation - + Hue - + Alpha - + Fade to Color - + Color @@ -7311,1015 +7606,1072 @@ Set the output folder path to the subfolder as well. PreferencesPopup - + Life is too short for Comic Sans - + Good luck. You're on your own from here. - - - + + + At Once - + New Level Format - + Assign the new level format name: - + New Format - + Numpad keys are assigned to the following commands. Is it OK to release these shortcuts? - + OK - + Cancel - + Preferences - + General - + Use Default Viewer for Movie Formats - + Minimize Raster Memory Fragmentation * - + Save Automatically - + Automatically Save the Scene File - + Automatically Save Non-Scene Files - + Show Startup Window when OpenToonz Starts - + Replace Toonz Level after SaveLevelAs command - + Backup Animation Levels when Saving - + Show Info in Rendered Frames - + Watch File System and Update File Browser Automatically - + My Documents/OpenToonz* - + Desktop/OpenToonz* - + Stuff Folder* - + Custom* - + Custom Project Path(s): - + Advanced: Multiple paths can be separated by ** (No Spaces) - - - - - + + + + + + * Changes will take effect the next time you run Toonz - + Interface - + All imported images will use the same DPI - + Move Current Frame by Clicking on Xsheet / Numerical Columns Cell Area - + Color Calibration using 3D Look-up Table * - + Enable auto-stretch frame - + Show Cursor Size Outlines - + Open Flipbook after Rendering - + Enable Actual Pixel View on Scene Editing Mode - + Display Level Name on Each Marker - + Show "ABC" Appendix to the Frame Number in Xsheet Cell - + Visualization - + Show Lines with Thickness 0 - + Loading - + Expose Loaded Levels in Xsheet - + Create Sub-folder when Importing Sub-xsheet - + Use Camera DPI for All Imported Images - + Automatically Remove Scene Number from Loaded Level Name - + Edit - + Import/Export - + Drawing - + DPI: - + New Levels Default to the Current Camera Size - + Keep Original Cleaned Up Drawings As Backup - + Multi Layer Style Picker : Switch Levels by Picking - + Use the TLV Savebox to Limit Filling Operations - + Minimize Savebox after Editing - + Use Numpad and Tab keys for Switching Styles - + Keep fill when using "Replace Vectors" command - + Use higher DPI for calculations - Slower but more accurate - + Tools - + Xsheet - + Xsheet Autopan during Playback - + Ignore Alpha Channel on Levels in Column 1 - + Show Keyframes on Cell Area - + Use Arrow Key to Shift Cell Selection - + Enable to Input Cells without Double Clicking - + Enable OpenToonz Commands' Shortcut Keys While Renaming Cell - + Show Toolbar in the XSheet - + Show Column Numbers in Column Headers - + Sync Level Strip Drawing Number Changes with the Xsheet - + Show Current Time Indicator (Timeline Mode only) - + Animation - + Preview - + Rewind after Playback - + Display in a New Flipbook Window - + Fit to Flipbook - + Onion Skin - + Onion Skin ON - + Show Onion Skin During Playback - + Display Lines Only - + Check for the Latest Version of OpenToonz on Launch - + Choosing this option will set initial location of all file browsers to $scenefolder. Also the initial output destination for new scenes will be set to $scenefolder as well. - + Graph Editor Opens in Popup - + Spreadsheet Opens in Popup - + Toggle Between Graph Editor and Spreadsheet - + Theme: - - Weight *: - - - - + OpenToonz can use FFmpeg for additional file formats. - + FFmpeg is not bundled with OpenToonz. - + Column Header Layout*: - + Transparency Check - + Version Control - + Show Raster Images Darken Blended - + Antialiased Region Boundaries - + + Saving + + + + Down Arrow at End of Level Strip Creates a New Frame - + Small - + Large - + Crosshair - + Default - + Left-Handed - + Simple - + Expand Function Editor Header to Match Xsheet Toolbar Height* - + Classic - + Classic-revised - + Compact - + + Use Onion Skin Colors for Reference Drawings of Shift and Trace + + + + Colors - + Enable Version Control* - + Automatically Refresh Folder Contents - + + Tablet Settings + + + + + Enable Windows Ink Support* (EXPERIMENTAL) + + + + Project Folder Aliases (+drawings, +scenes, etc.) - + Scene Folder Alias ($scenefolder) - + Use Project Folder Aliases Only - + This option defines which alias to be used if both are possible on coding file path. - + cm - + mm - + inch - + field - + pixel - + Mouse Cursor - + Viewer Center - - - + + + On Demand - + All Icons - + All Icons & Images - + Always ask before loading or importing - + Always import the file to the current project - + Always load the file from the current location - + Toonz Vector Level - + Toonz Raster Level - + Raster Level - + Disabled - + Enabled - + Use Xsheet as Animation Sheet - + Strokes - + Guides - + All - + Open the dropdown to display all options - + Cycle through the available options - + Cells Only - + Cells and Column Data - + Linear - + Speed In / Speed Out - + + Constant + + + + Ease In / Ease Out - + Ease In / Ease Out % - + + Exponential + + + + + Expression + + + + + File + + + + Arrow Markers - + Animated Guide - + Category - + Interval(Minutes): - + Undo Memory Size (MB) - + Render Task Chunk Size: - + Additional Project Locations - + Path Alias Priority: - + Pixels Only: - + Unit: - + Camera Unit: - + Rooms*: - + Function Editor*: - + Icon Size * - + X - + Viewer Shrink - + Step - + + Style *: + + + + 3DLUT File for [%1] *: - + + Matte color is used for background when overwriting raster levels with transparent pixels +in non alpha-enabled image format. + + + + + Matte color: + + + + Cursor Options - + Basic Cursor Type: - + Cursor Style: - + + Current Column Color: + + + + Viewer BG Color - + Preview BG Color - + ChessBoard Color 1 - + Chessboard Color 2 - + Viewer Zoom Center - + Language *: - + Font *: - + Default File Import Behavior: - + Default TLV Caching Behavior: - + Column Icon: - + Level Settings by File Format: - + Please provide the path where FFmpeg is located on your computer. - + FFmpeg Path: - + Number of seconds to wait for FFmpeg to complete processing the output: - + Note: FFmpeg begins working once all images have been processed. - + FFmpeg Timeout: - + Please indicate where you would like exports from Fast Render(MP4) to go. - + Fast Render Path: - + Scan File Format: - + Default Level Type: - + Width: - + Height: - + Autocreation: - + Vector Snapping: - + Replace Vectors with Simplified Vectors Command - + Dropdown Shortcuts: - + Next/Previous Step Frames: - + Cell-dragging Behaviour: - + Default Interpolation: - + Animation Step: - + Blank Frames: - + Blank Frames Color: - + Paper Thickness: - + Previous Frames Correction: - + Following Frames Correction: - + Vector Guided Style: - + Ink Color on White Bg: - + Ink Color on Black Bg: - + Paint Color: @@ -8327,22 +8679,22 @@ if both are possible on coding file path. PreferencesPopup::FormatProperties - + Level Settings by File Format - + Name: - + Regular Expression: - + Priority @@ -8350,12 +8702,12 @@ if both are possible on coding file path. Previewer - + The file name cannot be empty or contain any of the following characters:(new line) \ / : * ? " | - + File %1 already exists. Do you want to overwrite it? @@ -8561,17 +8913,17 @@ Do you want to overwrite it? QApplication - + New Scene - + Load Scene - + Quit @@ -8585,19 +8937,19 @@ Do you want to overwrite it? - - + + - - - - - - + + + + + + - + Overwrite @@ -8607,26 +8959,26 @@ Do you want to overwrite it? - + - - - + + + - + Yes - - + + - - - + + + - + No @@ -8638,85 +8990,90 @@ Do you want to overwrite it? - - - + + + - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - + + - - - + + + Cancel - + + Apply Antialias + + + + - - + + The current selection is invalid. - + Are you sure you want to override - + Override - + It is not possible to save the curve. - + It is not possible to load the curve. - + It is not possible to export data. @@ -8754,18 +9111,18 @@ Save the scene first. - - + + The resolution of the output camera does not fit with the options chosen for the output file format. - + FFmpeg not found, please set the location in the Preferences and restart. - + It is not possible to complete the rendering. @@ -8805,7 +9162,7 @@ Save the scene first. - + Cleanup Settings @@ -8817,8 +9174,8 @@ Save the scene first. - - + + Don't Overwrite @@ -8839,8 +9196,8 @@ Do you want to save your changes? - - + + Save @@ -8876,7 +9233,7 @@ Are you sure ? - + Delete @@ -8886,33 +9243,48 @@ Are you sure ? - + Deactivate Onion Skin - + Limit Onion Skin To Level - + Extend Onion Skin To Scene - + + Clear All Onion Skin Markers + + + + + Clear All Fixed Onion Skin Markers + + + + + Clear All Relative Onion Skin Markers + + + + Activate Onion Skin - - + + Saving previewed frames.... - + %1 has an invalid extension format. @@ -9029,43 +9401,43 @@ Are you sure ? - + Insert Frame at Frame %1 - + Remove Frame at Frame %1 - + Insert Multiple Keys at Frame %1 - + Remove Multiple Keys at Frame %1 - - + + Change current drawing %1 - + New Note Level - + Set Keyframe : %1 - + The %1 file has been generated @@ -9129,38 +9501,38 @@ Are you sure ? - + Delete Level : %1 - + No unused levels - + It is not possible to delete the used level %1. - + No cleaned up drawings available for the current selection. - + No saved drawings available for the current selection. - + Revert To %1 : Level %2 - - The Revert to Last Saved command is not supported for the current selection. + + The Reload command is not supported for the current selection. @@ -9222,101 +9594,107 @@ Do you want to import it or load it from its original location? - + %1: the current scene has been modified. What would you like to do? - + Save All - + Save Scene Only - + Discard Changes - + The following file(s) have been modified. - + What would you like to do? - + Save Changes - + Anyway - + %1 has an invalid file extension. - + %1 is an invalid path. - + The scene %1 already exists. Do you want to overwrite it? - - - + + Couldn't load %1 + + + + + + + Couldn't save %1 - + The level %1 already exists. Do you want to overwrite it? - + Overwrite Palette - + Don't Overwrite Palette - + The soundtrack %1 already exists. Do you want to overwrite it? - + File %1 doesn't look like a TOONZ Scene - + A prior save of Scene '%1' was critically interupted. A partial save file was generated and changes may be manually salvaged from '%2'. @@ -9325,33 +9703,33 @@ Do you wish to continue loading the last good save or stop and try to salvage th - + Continue - + It is not possible to load the scene %1 because it does not belong to any project. - + The Scene '%1' belongs to project '%2'. What do you want to do? - + Import Scene - + Change Project - + There were problems loading the scene %1. @@ -9359,165 +9737,165 @@ What do you want to do? - + There were problems loading the scene %1. Some levels have not been loaded because their version is not supported - + This scene is incompatible with pixels only mode of the current OpenToonz version. What would you like to do? - + Turn off pixels only mode - + Keep pixels only mode on and resize the scene - + File '%1' will reload level '%2' as a duplicate column in the xsheet. Allow duplicate? - + Allow - + Allow All Dups - + No to All Dups - - + + It is not possible to load the level %1 - + The following level(s) use path with $scenefolder alias. - + They will not be opened properly when you load the scene next time. What do you want to do? - + Copy the levels to correspondent paths - + Decode all $scenefolder aliases - + Save the scene only - + File %1 already exists. Do you want to overwrite it? - + Overwrite for All - + Don't Overwrite for All - - + + Failed to overwrite %1 - + No Current Level - + No Current Scene - + Save the scene first - + Save level Failed - + Are you sure you want to save the Default Settings? - + It is not possible to load the %1 level. - + The scene %1 doesn't exist. - + Revert: the current scene has been modified. Are you sure you want to revert to previous version? - + Revert - - - + + + OK - + The copied selection cannot be pasted in the current drawing. @@ -9589,114 +9967,114 @@ Are you sure you want to revert to previous version? - + It is not possible to paste the columns: there is a circular reference. - + Paste Column : - + Delete Column : - + Insert Column : - + Resequence : Col%1 - + Clone Sub-xsheet : Col%1 - + Clear Cells : Col%1 - + Reverse - + Swing - + Autoexpose - + Invalid selection: each selected column must contain one single level with increasing frame numbering. - + Random - + Step %1 - + Each %1 - + Reframe to %1's - + Reframe to %1's with %2 blanks - + Roll Up - + Roll Down - + Clone Level : %1 > %2 - + Clone Levels : - + Ok - + FlipBook @@ -9813,8 +10191,8 @@ Are you sure? - - + + Script Console @@ -9881,7 +10259,7 @@ Are you sure? - + Run script @@ -9891,12 +10269,12 @@ Are you sure? - + Image DPI - + Custom DPI @@ -9907,11 +10285,21 @@ Are you sure? - Warning + Error + No Palette loaded. + + + + + Warning + + + + Palette is locked. @@ -9922,12 +10310,12 @@ Are you sure? - + Create Level %1 at Column %2 - + Layer name @@ -9976,249 +10364,275 @@ Do you want to overwrite it? - - + + File Browser - + Duplicate - + Paste Key Frames - + Delete Key Frames - + Copy File - + Paste File : - + Duplicate File : - + Task added to the Batch Render List. - + Task added to the Batch Cleanup List. - + Deleting %1. Are you sure? - + Deleting %n files. Are you sure? - + A convertion task is in progress! wait until it stops or cancel it - + You are going to premultiply selected files. The operation cannot be undone: are you sure? - + Premultiply - + There are no assets to collect - + One asset imported - + %1 assets imported - + + A separation task is in progress! wait until it stops or cancel it + + + + Error loading scene %1 :%2 - + Error loading scene %1 - + There was an error saving the %1 scene. - + No scene imported - + One scene imported - + %1 scenes imported - + It is not possible to delete the selection. - + Paste Cells - + Delete Cells - + Cut Cells - + Insert Cells - + It is not possible to paste vectors in the current cell. - + Paste (Strokes) - + It is not possible to paste image on the current cell. - - + + Paste - + Paste (Raster) - + Overwrite Paste Cells - + Paste Numbers - - + + Rename Cell at Column %1 Frame %2 - + Fill In Empty Cells - - - + + Duplicate Frame in XSheet + + + + + + No data to paste. - - - + + + It is not possible to paste the cells: there is a circular reference. - - + + It is not possible to paste data: there is nothing to paste. - - + + Please enable "Sync Level Strip Drawing Number Changes with the XSheet" preference option +to use the duplicate command in the xsheet / timeline. + + + + + Please select only one layer to duplicate a frame. + + + + + Please select only one frame to duplicate. + + + + + Cannot paste data Nothing to paste - + It is not possible to paste the cells: Some column is locked or column type is not match. - - + + This command only works on vector cells. - + Please select only one column for this command. - + All selected cells must belong to the same level. - + Simplify Vectors : Level %1 @@ -10233,11 +10647,16 @@ The operation cannot be undone: are you sure? - + Xsheet + + Timeline + + + Modify Play Range : %1 - %2 @@ -10268,129 +10687,129 @@ The operation cannot be undone: are you sure? - + Change Pegbar - + Change Text at Column %1 Frame %2 - + Toggle cycle of %1 - + Move Level - - + + Schematic - + Stage Schematic - + Fx Schematic - + Palette - - + + Studio Palette - - + + Style Editor - - + + Viewer - + Command Bar - + Tool Options - + Tasks - + Batch Servers - - + + Scene Cast - - + + Export - - + + Function Editor - - + + Message Center - + LineTest Viewer - + LineTest Capture - - + + Combo Viewer - - + + History @@ -10444,37 +10863,37 @@ The operation cannot be undone: are you sure? - + Level: - + Skipping frame. - + Don't Duplicate - + The specified name is already assigned to the %1 file. - + Warning: level %1 already exists; overwrite? - + It is not possible to rename the %1 file. - + It is not possible to copy the %1 file. @@ -10494,7 +10913,7 @@ The operation cannot be undone: are you sure? - + Move Level to Cast Folder @@ -10537,7 +10956,7 @@ The operation cannot be undone: are you sure? - + It is possible to merge only Toonz vector levels or standard raster levels. @@ -10621,52 +11040,57 @@ The operation cannot be undone: are you sure? - + Cannot open menubar settings template file. Re-installing Toonz will solve this problem. - + No more Undo operations available. - + No more Redo operations available. - + The rooms will be reset the next time you run Toonz. - + Visit Web Site - + An update is available for this software. Visit the Web site for more information. - + Check for the latest version on launch. - + https://opentoonz.github.io/e/ - + Installing %1 again could fix the problem. + + The qualifier %1 is not a valid key name. Skipping. + + + Selected folders don't belong to the current project. Do you want to import them or load from their original location? @@ -10724,38 +11148,38 @@ Do you want to import them or load from their original location? RenameAsToonzPopup - + The file name cannot be empty or contain any of the following characters:(new line) \ / : * ? " | - - + + Rename - + Renaming File - + Creating an animation level of %1 frames - + Delete Original Files - + Level Name: - + Cancel @@ -11204,79 +11628,79 @@ The audio file will not be included in the rendered clip. SVNLockDialog - + Version Control: Edit - + Version Control: Unlock - + Getting repository status... - + Comment: - + Edit Scene Contents - + Unlock Scene Contents - + Edit - + Unlock - + Cancel - + No items to edit. - + No items to unlock. - - + + %1 items to edit. - - + + %1 items to unlock. - + Editing %1 items... - + Unlocking %1 items... @@ -11338,32 +11762,32 @@ The audio file will not be included in the rendered clip. SVNLockInfoDialog - + Version Control: Edit Info - + <b>Edited By:</b> - + <b>Host:</b> - + <b>Comment:</b> - + <b>Date:</b> - + Close @@ -11903,14 +12327,22 @@ Please commit or revert changes first. + SaveBoardPresetFilePopup + + + Save Clapperboard Settings As Preset + + + + SaveCurvePopup - + Save Curve - + Save @@ -11918,12 +12350,12 @@ Please commit or revert changes first. SaveImagesPopup - + Save Flipbook Images - + Save @@ -12000,12 +12432,12 @@ Please commit or revert changes first. SavePreviewedPopup - + Save Previewed Images - + Save @@ -12259,218 +12691,424 @@ Please commit or revert changes first. SceneViewerPanel - + Safe Area (Right Click to Select) - + Field Guide - + Camera Stand View - + 3D View - + Camera View - + Freeze - + Preview - + Sub-camera Preview - + Untitled - + Scene: - + :: Frame: - - + + :: Zoom : - - + + (Flipped) - + :: Level: - + Level: + SeparateColorsPopup + + + Auto + + + + + Preview + + + + + Separate + + + + + Close + + + + + Sub Color 3: + + + + + Alpha Matting + + + + + Main + + + + + Sub1 + + + + + Sub2 + + + + + Sub3 + + + + + Pick Color + + + + + Show Mask + + + + + Show Alpha + + + + + Preview Frame: + + + + + Paper Color: + + + + + Main Color: + + + + + Sub Color 1: + + + + + Sub Color 2: + + + + + Sub Adjust: + + + + + Border Smooth: + + + + + Mask Threshold: + + + + + Mask Radius: + + + + + Start: + + + + + End: + + + + + Format: + + + + + Save in: + + + + + File Suffix: + + + + + Cancel + + + + + Separate by colors ... + + + + + Separate 1 Level + + + + + Separate %1 Levels + + + + + Critical + + + + + Failed to access the destination folder! + + + + + Separating %1 + + + + + Converting level %1 of %2: %3 + + + + + SeparateSwatch + + + Sub Color 3 + + + + + Original + + + + + Main Color + + + + + Sub Color 1 + + + + + Sub Color 2 + + + + ShortcutPopup - + Configure Shortcuts - + Remove + - Export Current Shortcuts - + Delete - + Delete Current Preset - + Save As - + Save Current Shortcuts as New Preset - + Load - + Use selected preset as shortcuts - + Shortcut Presets - + Clear All Shortcuts - + Couldn't find any matching command. - + Search: - + Preset: - + This will erase ALL shortcuts. Continue? - + This will overwrite all current shortcuts. Continue? - + A file named - + already exists. Do you want to replace it? - + OpenToonz - Setting Shortcuts - + Saving Shortcuts - + Included presets cannot be deleted. - + Are you sure you want to delete the preset: - + ? - + Setting Shortcuts - + Load from file... - + Enter Preset Name - + Preset Name: @@ -12478,112 +13116,112 @@ Please commit or revert changes first. ShortcutTree - + Menu Commands - + Fill - + File - + Edit - + Scan & Cleanup - + Level - + Xsheet - + Cells - + View - + Windows - + Right-click Menu Commands - + Tools - + Tool Modifiers - + Visualization - + Misc - + Playback Controls - + RGBA Channels @@ -12598,18 +13236,18 @@ Please commit or revert changes first. ShortcutViewer - + %1 is already assigned to '%2' Assign to '%3'? - + Yes - + No @@ -12629,16 +13267,16 @@ Assign to '%3'? - - - - + + + + Files - + Scan @@ -12654,149 +13292,149 @@ Assign to '%3'? - - - - + + + + Edit - - - - - + + + + + Windows - - - - + + + + Other Windows - - - - - - + + + + + + Customize - - - - - + + + + + View - - - - - - - + + + + + + + Help - - + + Tools - - + + More Tools - - + + Checks - - + + Render - + Draw - - + + Xsheet - + Subxsheet - + Levels - - + + Cells - + Reframe - + Step - + Each - + File - + Scan && Cleanup - + Level - + Cannot open menubar settings file %1 - + Failed to create menubar @@ -13439,7 +14077,7 @@ Possibly the preset file has been corrupted TopBar - + Lock Rooms Tab @@ -13697,27 +14335,27 @@ Possibly the preset file has been corrupted VersionControl - + The version control configuration file is empty or wrongly defined. Please refer to the user guide for details. - + The version control client application specified on the configuration file cannot be found. Please refer to the user guide for details. - - + + The version control client application is not installed on your computer. Subversion 1.5 or later is required. Please refer to the user guide for details. - + The version control client application installed on your computer needs to be updated, otherwise some features may not be available. Subversion 1.5 or later is required. Please refer to the user guide for details. @@ -13735,87 +14373,87 @@ Please refer to the user guide for details. XsheetGUI::CellArea - + Click to select keyframe, drag to move it - + Click and drag to set the acceleration range - + Click and drag to set the deceleration range - + Set the cycle of previous keyframes - + Click and drag to move the selection - + Click and drag to play - + Click and drag to repeat selected cells - + Reframe - + Step - + Each - + Edit Cell Numbers - + Replace Level - + Replace with - + Paste Special - + Edit Image - + Open Memo - + Delete Memo @@ -13823,135 +14461,135 @@ Please refer to the user guide for details. XsheetGUI::ColumnArea - + &Subsampling 1 - + &Subsampling 2 - + &Subsampling 3 - + &Subsampling 4 - + Click to select camera - - + + Click to select column, drag to move it - + Click to select column - + Click to select column, drag to move it, double-click to edit - - + + Click to play the soundtrack back - - + + Set the volume of the soundtrack - + Click to select column, double-click to edit - + Lock Toggle - + Additional column settings - + Preview Visibility Toggle - + Camera Stand Visibility Toggle - + Alt + Click to Toggle Thumbnail - + Reframe - + Subsampling - + &Insert Before - + &Insert After - + &Paste Insert Before - + &Paste Insert After - + &Insert Below - + &Insert Above - + &Paste Insert Below - + &Paste Insert Above @@ -13959,30 +14597,55 @@ Please refer to the user guide for details. XsheetGUI::ColumnTransparencyPopup - + Filter: + + + Opacity: + + XsheetGUI::NoteArea - + + Toggle Xsheet/Timeline + + + + + Add New Memo + + + + + Previous Memo + + + + + Next Memo + + + + Frame - + Sec Frame - + 6sec Sheet - + 3sec Sheet @@ -14008,67 +14671,98 @@ Please refer to the user guide for details. XsheetGUI::RowArea - + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + + Click to Move Shift & Trace Marker + + + + Playback Start Marker - + Playback End Marker - + Pinned Center : Col%1%2 - + Double Click to Toggle Onion Skin - + Current Frame - + Fixed Onion Skin Toggle - + Relative Onion Skin Toggle - + Set Start Marker - + Set Stop Marker - + Set Auto Markers - + Remove Markers - + Preview This + XsheetGUI::SoundColumnPopup + + + Volume: + + + + XsheetGUI::XSheetToolbar diff --git a/toonz/sources/translations/korean/toonzlib.ts b/toonz/sources/translations/korean/toonzlib.ts index d91e464..48a3131 100644 --- a/toonz/sources/translations/korean/toonzlib.ts +++ b/toonz/sources/translations/korean/toonzlib.ts @@ -4,17 +4,17 @@ Preferences - + Retas Level Format - + Adobe Photoshop - + PNG @@ -153,62 +153,62 @@ - + Arrange Styles in Palette %1 - + Create Style#%1 in Palette %2 - + Add Style to Palette %1 - + Add Page %1 to Palette %2 - + Delete Page %1 from Palette %2 - + Load Color Model %1 to Palette %2 - + color model - + Move Page - + Rename Page %1 > %2 - + Rename Style#%1 in Palette%2 : %3 > %4 - + Set Picked Position of Style#%1 in Palette%2 : %3,%4 - + Update Colors by Using Picked Positions in Palette %1 @@ -229,82 +229,82 @@ - + Replace Fx : - + Unlink Fx : %1 - - %2 - + Make Macro Fx : %1 - + Explode Macro Fx : %1 - + Create Output Fx - + Connect to Xsheet : - + Disconnect from Xsheet : - + Delete Link - + Delete Fx Node : %1 - + Paste Fx : - + Disconnect Fx - + Connect Fx : %1 - %2 - + Rename Fx : %1 > %2 - + Group Fx - + Ungroup Fx - + Rename Group : %1 > %2 @@ -452,7 +452,7 @@ - + Argument '%1' does not look like a FrameId @@ -467,22 +467,22 @@ - + %1-%2 - + %1 - + Expected %1 argument(s) in %2, got %3 - + %1 is not a valid color (valid color names are 'red', 'transparent', '#FF8800', ecc.) @@ -537,12 +537,12 @@ - + Xsheet - + Timeline @@ -653,77 +653,77 @@ TScriptBinding::Level - + %1 frames - + Bad argument (%1). It should be FilePath or string - + Exception loading level (%1) - + File %1 doesn't exist - + File %1 is unsupported - + Exception reading %1 - + Can't save an empty level - + Unrecognized file type : - + Can't save a %1 level to this file type : %2 - + Exception writing %1 - + frame index (%1) must be a number - + frame index (%1) is out of range (0-%2) - + second argument (%1) is not an image - + can not insert a %1 image into a level - + can not insert a %1 image to a %2 level diff --git a/toonz/sources/translations/korean/toonzqt.ts b/toonz/sources/translations/korean/toonzqt.ts index d9c9a33..4c5867e 100644 --- a/toonz/sources/translations/korean/toonzqt.ts +++ b/toonz/sources/translations/korean/toonzqt.ts @@ -91,12 +91,12 @@ CameraPainter - + &Reset Center - + &Activate @@ -104,81 +104,81 @@ CameraSettingsWidget - + DPI - - - + + + Pixels - + x - + Use Current Level Settings - + Add - + Remove - + Force Squared Pixel - + A/R - - + + <custom> - + Bad camera preset - + '%1' doesn't seem a well formed camera preset. Possibly the preset file has been corrupted - + Preset name - + Enter the name for %1 - + Error : Preset Name is Invalid - + The preset name must not use ','(comma). @@ -227,15 +227,10 @@ Possibly the preset file has been corrupted ColumnPainter - + &Reset Center - - - &Open Subxsheet - - ComboHistoRGBLabel @@ -284,32 +279,32 @@ Possibly the preset file has been corrupted DVGui::CleanupColorField - + Brightness: - + Contrast: - + Color Thres - + White Thres - + H Range - + Line Width @@ -317,22 +312,22 @@ Possibly the preset file has been corrupted DVGui::ColorField - + R: - + G: - + B: - + A: @@ -373,7 +368,7 @@ Possibly the preset file has been corrupted DVGui::FileField - + ... @@ -406,7 +401,7 @@ Possibly the preset file has been corrupted DVGui::StyleIndexLineEdit - + current @@ -466,17 +461,17 @@ Possibly the preset file has been corrupted FileSegmentPage - + File Path: - + Column: - + Unit: @@ -711,6 +706,19 @@ Possibly the preset file has been corrupted + FontParamField + + + Style: + + + + + Size: + + + + FrameNavigator @@ -750,127 +758,127 @@ Possibly the preset file has been corrupted - + Link Handles - + Unlink Handles - + Reset Handles - + Delete - + Set Key - + Activate Cycle - + Deactivate Cycle - + Linear Interpolation - + Speed In / Speed Out Interpolation - + Ease In / Ease Out Interpolation - + Ease In / Ease Out (%) Interpolation - + Exponential Interpolation - + Expression Interpolation - + File Interpolation - + Constant Interpolation - + Similar Shape Interpolation - + Fit Selection - + Fit - + Step 1 - + Step 2 - + Step 3 - + Step 4 - + Smooth - + Frame Based - + Curve Shape @@ -878,126 +886,126 @@ Possibly the preset file has been corrupted FunctionSegmentViewer - - + + Linear - + Speed In / Speed Out - + Ease In / Ease Out - + Ease In / Ease Out % - + Exponential - + Expression - - + + File - + Constant - + Similar Shape - + Interpolation: - + Apply - + From - + To - + Step - - + + < - - + + > - + Speed - + Ease - + Ease% - + Expo - + Expr - + Const - + Similar - + ???? @@ -1160,55 +1168,50 @@ Possibly the preset file has been corrupted FxColumnPainter - + &Disconnect from Xsheet - + &Connect to Xsheet - + &Paste Add - + &Preview - + &Uncache Fx - + &Cache FX - - - &Open Subxsheet - - FxOutputPainter - + Output - + &Delete - + &Activate @@ -1216,77 +1219,77 @@ Possibly the preset file has been corrupted FxPainter - + &Open Group - + &Paste Replace - + &Paste Add - + &Delete - + &Disconnect from Xsheet - + &Connect to Xsheet - + &Create Linked FX - + &Unlink - + &Make Macro FX - + &Explode Macro FX - + &Open Macro FX - + &Save As Preset... - + &Preview - + &Uncache FX - + &Cache FX @@ -1294,17 +1297,17 @@ Possibly the preset file has been corrupted FxPalettePainter - + &Disconnect from Xsheet - + &Connect to Xsheet - + &Preview @@ -1312,25 +1315,33 @@ Possibly the preset file has been corrupted FxSchematicLink - + &Delete - + &Paste Insert + FxSchematicOutputNode + + + Output + + + + FxSchematicPort - + &Disconnect from Xsheet - + &Connect to Xsheet @@ -1338,25 +1349,33 @@ Possibly the preset file has been corrupted FxSchematicScene - + Cannot Paste Insert a selection of unconnected FX nodes. Select FX nodes and related links before copying or cutting the selection you want to paste. - + Cannot Paste Add a selection of unconnected FX nodes. Select FX nodes and related links before copying or cutting the selection you want to paste. - + Cannot Paste Replace a selection of unconnected FX nodes. Select FX nodes and related links before copying or cutting the selection you want to paste. + FxSchematicXSheetNode + + + XSheet + + + + FxSettings @@ -1397,17 +1416,17 @@ Select FX nodes and related links before copying or cutting the selection you wa FxXSheetPainter - + XSheet - + &Paste Add - + &Preview @@ -1415,7 +1434,7 @@ Select FX nodes and related links before copying or cutting the selection you wa GroupPainter - + &Open Group @@ -1655,22 +1674,22 @@ Select FX nodes and related links before copying or cutting the selection you wa PaletteViewerGUI::PageViewer - + - No Styles - - + Name Editor - + New Style - + New Page @@ -1717,7 +1736,7 @@ Select FX nodes and related links before copying or cutting the selection you wa PegbarPainter - + &Reset Center @@ -1725,12 +1744,12 @@ Select FX nodes and related links before copying or cutting the selection you wa PointParamField - + X: - + Y: @@ -1738,19 +1757,19 @@ Select FX nodes and related links before copying or cutting the selection you wa QObject - + Deleting "%1". Are you sure? - - + + Delete - + @@ -1852,7 +1871,7 @@ Are you sure? - + Paste Object @@ -1877,38 +1896,38 @@ Are you sure? - + Save Motion Path - - + + Motion Path files (*.mpath) - + It is not possible to save the motion path. - + Load Motion Path - + It is not possible to load the motion path. - + Stage Schematic - + FX Schematic @@ -1945,67 +1964,68 @@ Are you sure? - + + Modify Fx Param : %1 - - - + + + Modify Fx Param : %1 : %2 -> %3 - - + + Modify Fx Param : - + ON : %1 - + OFF : %1 - + Modify Fx Param : %1 : %2 Key - - + + Add - - + + Remove - + Modify Fx Param : %1 : %2 Point - + %1 : Linear ON - + %1 : Linear OFF - + Palette @@ -2234,6 +2254,8 @@ Are you sure? + + The source image seems not suitable for this kind of conversion @@ -2305,12 +2327,12 @@ Are you sure? - + Modify Fx Param : %1 Key : %2 Frame %3 - + Set @@ -2394,59 +2416,64 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< SchematicViewer - + &Fit to Window - + &Focus on Current - + &Reorder Nodes - + &Reset Size - - - + + + &Minimize Nodes - - - + + + &Maximize Nodes - + &New Pegbar - + &New Camera - + &New Motion Path - + &Swtich output port display mode + + + &Toggle node icons + + SchematicWindowEditor @@ -2459,22 +2486,22 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< SimilarShapeSegmentPage - + Reference Curve: - + Frame Offset: - + There is a syntax error in the definition of the interpolation. - + There is a circular reference in the definition of the interpolation. @@ -2525,17 +2552,17 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< SplinePainter - + &Delete - + &Save Motion Path... - + &Load Motion Path... @@ -2543,17 +2570,17 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< StageSchematicScene - + &New Pegbar - + &New Motion Path - + &New Camera @@ -2905,12 +2932,12 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< TablePainter - + Table - + &Reset Center diff --git a/toonz/sources/translations/russian/image.ts b/toonz/sources/translations/russian/image.ts index 7c95c32..efc8b7a 100644 --- a/toonz/sources/translations/russian/image.ts +++ b/toonz/sources/translations/russian/image.ts @@ -4,12 +4,12 @@ AviWriterProperties - + Codec Кодек - + Uncompressed Без сжатия @@ -70,52 +70,52 @@ Please try raising the FFmpeg timeout in Preferences. SgiWriterProperties - + Bits Per Pixel Битов на пиксель - + 24 bits 24 бита - + 32 bits 32 бита - + 48 bits 48 бита - + 64 bits 64 бита - + 8 bits (Greyscale) 8 бита (оттенки серого) - + Endianess Порядок байтов - + Big Endian - + Little Endian - + RLE-Compressed RLE-сжатие @@ -181,37 +181,37 @@ Please try raising the FFmpeg timeout in Preferences. SvgWriterProperties - + Stroke Mode Режим обводки - + Outline Quality Качество контура - + Centerline Осевая линия - + Outline Контур - + High Высокая - + Medium Средняя - + Low Низкая @@ -340,12 +340,12 @@ Please try raising the FFmpeg timeout in Preferences. WebmWriterProperties - + Quality Качество - + Scale Масштаб diff --git a/toonz/sources/translations/russian/tnzcore.ts b/toonz/sources/translations/russian/tnzcore.ts index 0342765..5fcd24d 100644 --- a/toonz/sources/translations/russian/tnzcore.ts +++ b/toonz/sources/translations/russian/tnzcore.ts @@ -4,17 +4,17 @@ BmpWriterProperties - + Bits Per Pixel Битов на пиксель - + 24 bits 24 бита - + 8 bits (Greyscale) 8 бит (оттенки серого) @@ -22,12 +22,12 @@ JpgWriterProperties - + Quality Качество - + Smoothing Сглаживание @@ -58,12 +58,12 @@ TCenterLineStrokeStyle - + Constant Постоянная - + Thickness Толщина @@ -71,12 +71,12 @@ TRasterImagePatternStrokeStyle - + Distance Расстояние - + Rotation Вращение @@ -84,12 +84,12 @@ TVectorImagePatternStrokeStyle - + Distance Расстояние - + Rotation Вращение diff --git a/toonz/sources/translations/russian/tnztools.ts b/toonz/sources/translations/russian/tnztools.ts index 0cd0b6a..cdbc188 100644 --- a/toonz/sources/translations/russian/tnztools.ts +++ b/toonz/sources/translations/russian/tnztools.ts @@ -4,107 +4,107 @@ ArrowToolOptionsBox - - + + E/W: запад/восток X: - - + + N/S: север/юг Y: - + SO: порядок размещения: Порядок: - + Position Положение - + Z: глубина Z: - + ( ( - + ) ) - + Rotation Вращение - + Scale Масштаб - + Global: Глобальный: - + Position: Положение: - + Rotation: Вращение: - - + + H: горизонтально H: - - + + V: вертикально V: - + Maintain: Поддерживать: - + Shear Скос - + Center Position Центральное положение - + Table - + Pick: Выбрать: @@ -112,23 +112,21 @@ BrushTool - - + Size Размер - Hardness: - Жесткость: + Жесткость: - + Accuracy: Точность: - + Smooth: Плавность: @@ -137,143 +135,138 @@ Избирательно - Draw Order: - Порядок рисовки: + Порядок рисовки: - Over All - Над всеми + Над всеми - Under All - Под всеми + Под всеми - Palette Order - Порядок палитры + Порядок палитры - + Preset: Предустановка: - - + + <custom> <пользовательский> - + Break Разрыв - Pencil - Карандаш + Карандаш - + Pressure Нажим - + Cap Конец - + Join Соединение - + Miter: Скос: - + Range: Диапазон: - + Snap Привязка - + Off Выкл - + Linear Линейный - + In Вход - + Out Выход - + In&Out Вход и &выход - + Low Низкий - + Med Средний - + High Высокий - + Butt cap - + Round cap - + Projecting cap - + Miter join - + Round join - + Bevel join @@ -281,17 +274,17 @@ BrushToolOptionsBox - + Preset Name Имя предустановки - + OK OK - + Cancel Отмена @@ -320,7 +313,7 @@ DVGui::StyleIndexLineEdit - + current текущий @@ -491,85 +484,85 @@ EraserTool - + Size: Размер: - + Selective Избирательно - + Invert Инвертировать - + Frame Range Диапазон кадров - + Type: Тип: - + Normal Обычное - + Rectangular Прямоугольное - + Freehand От руки - + Polyline Полилиния - + Hardness: Жесткость: - + Mode: Режим: - + Lines Линии - + Areas Области - + Lines & Areas Линии и области - + Pencil Mode Режим карандаша @@ -660,12 +653,12 @@ FingerTool - + Size: Размер: - + Invert Инвертировать @@ -710,7 +703,7 @@ Заблокировать альфа канал - + <custom> <пользовательский> @@ -718,52 +711,52 @@ FullColorEraserTool - + Size: Размер: - + Opacity: Непрозрачность: - + Hardness: Жесткость: - + Type: Тип: - + Normal Обычное - + Rectangular Прямоугольное - + Freehand От руки - + Polyline Полилиния - + Invert Обратить - + Frame Range Диапазон кадров @@ -787,32 +780,32 @@ PaintBrushTool - + Size: Размер: - + Mode: Режим: - + Lines Линии - + Areas Области - + Lines & Areas Линии и области - + Selective Избирательно @@ -820,17 +813,17 @@ PinchTool - + Size: Размер: - + Corner: Угол: - + Manual Вручную @@ -838,22 +831,22 @@ PlasticTool - + Swap Edge Поменять ребро - + Collapse Edge Убрать ребро - + Split Edge Разделить ребро - + Cut Mesh Резать полисетку @@ -953,7 +946,7 @@ Угол привязки - + A group of skeletons already exists for current column. Replacing it will also substitute any existing vertex animation. Do you want to continue? @@ -962,48 +955,48 @@ Do you want to continue? Вы хотите продолжить? - + Ok OK - + Cancel Отмена - + Copy Skeleton Копировать скелет - + Paste Skeleton Вставить скелет - + Show Mesh Показать полисетку - + Show Rigidity Показать жесткость - + Show SO SO - порядок перекрытия Показать порядок - + Show Skeleton Onion Skin Показать кальку скелета - + The previous vertex name will be discarded, and all associated keys will be lost. Do you want to proceed? @@ -1211,25 +1204,25 @@ Do you want to proceed? QObject - + The copied selection cannot be pasted in the current drawing. Скопированное выделение невозможно вставить в текущий рисунок. - - + + Paste Вставить - - + + Min: Мин: - - + + Max: Макс: @@ -1249,12 +1242,12 @@ Do you want to proceed? RGB Пипетка (R%1, G%2, B%3) - + Ok ОК - + Cancel Отмена @@ -1294,19 +1287,19 @@ Do you want to proceed? Переместить группу + - Yes Да + - No Нет - + Modify Fx Gadget Изменить Fx-гаджет @@ -1453,7 +1446,7 @@ Do you want to proceed? RGBPickerToolOptionsBox - + Pick Screen Экранный выбор @@ -1540,37 +1533,37 @@ Do you want to proceed? RulerToolOptionsBox - + X: ruler tool option X: - + Y: ruler tool option Y: - + W: ruler tool option Ш: - + H: ruler tool option В: - + A: ruler tool option У: - + L: ruler tool option Д: @@ -1602,42 +1595,76 @@ Do you want to proceed? SelectionToolOptionsBox - + H: H: - + V: V: - + Link Связать - + + Rotation Вращение - + E/W: E/W: - + N/S: N/S: - + + Scale + Масштаб + + + + Position + Положение + + + Thickness Толщина + ShiftTraceToolOptionBox + + + Reset Previous + + + + + Reset Following + + + + + Previous Drawing + + + + + Following Drawing + + + + SkeletonTool @@ -1726,13 +1753,73 @@ Do you want to proceed? StylePickerToolOptionsBox - + With this option being activated, the picked style will be moved to the end of the first page of the palette. При активации этого параметра, выбранный стиль будет перемещен в конец первой страницы палитры. + ToonzRasterBrushTool + + + + Size + Размер + + + + Hardness: + Жесткость: + + + + Smooth: + Плавность: + + + + Draw Order: + Порядок рисовки: + + + + Over All + Над всеми + + + + Under All + Под всеми + + + + Palette Order + Порядок палитры + + + + Preset: + Предустановка: + + + + + <custom> + <пользовательский> + + + + Pencil + Карандаш + + + + Pressure + Нажим + + + TrackerTool @@ -1758,22 +1845,22 @@ moved to the end of the first page of the palette. TypeTool - + Font: Шрифт: - + Style: Начертание: - + Vertical Orientation Вертикальная ориентация - + Size: Размер: diff --git a/toonz/sources/translations/russian/toonz.ts b/toonz/sources/translations/russian/toonz.ts index a5cd28b..5a52677 100644 --- a/toonz/sources/translations/russian/toonz.ts +++ b/toonz/sources/translations/russian/toonz.ts @@ -144,28 +144,28 @@ AudioRecordingPopup - + Audio Recording Запись аудио - + Save and Insert Сохранить и вставить - + Sync with XSheet Синхронизация с XSheet - - + + - + The microphone is not available: Please select a different device or check the microphone. Микрофон недоступен: @@ -216,7 +216,7 @@ pick up all frames in the selected level. with - + с @@ -453,6 +453,112 @@ Do you want to save your changes? + BoardSettingsPopup + + + Clapperboard Settings + + + + + Load Preset + + + + + Save as Preset + + + + + Close + Закрыть + + + + Duration (frames): + + + + + Text + + + + + Project name + + + + + Scene name + + + + + Duration : Frame + + + + + Duration : Sec + Frame + + + + + Duration : HH:MM:SS:FF + + + + + Current date + + + + + Current date and time + + + + + User name + + + + + Scene location : Aliased path + + + + + Scene location : Full path + + + + + Output location : Aliased path + + + + + Output location : Full path + + + + + Image + + + + + BoardView + + + Please set the duration more than 0 frame first, or the clapperboard settings will not be saved in the scene at all! + + + + BrightnessAndContrastPopup @@ -718,27 +824,27 @@ Do you want to crop the canvas? CastBrowser - + It is not possible to edit the selected file. Редактировать выбранный файл невозможно. - + It is not possible to edit more than one file at once. Невозможно одновременно редактировать несколько файлов. - + It is not possible to show the folder containing the selected file, as the file has not been saved yet. Невозможно показать папку, содержащую выбранный файл, поскольку файл еще не сохранен. - + It is not possible to view the selected file, as the file has not been saved yet. Невозможно просмотреть выбранный файл, так как файл еще не сохранен. - + It is not possible to show the info of the selected file, as the file has not been saved yet. Невозможно показать информацию о выбранном файле, так как файл еще не сохранен. @@ -746,17 +852,17 @@ Do you want to crop the canvas? CastTreeViewer - + Delete folder Удалить папку - + Yes Да - + No Нет @@ -1187,12 +1293,12 @@ What do you want to do? CloneLevelUndo::LevelNamePopup - + Clone Level Клонировать уровень - + Level Name: Имя уровня: @@ -1323,94 +1429,94 @@ What do you want to do? ComboViewerPanel - + GUI Show / Hide Показать / скрыть GUI - + Toolbar Панель инструментов - + Tool Options Bar Панель настройки инструментов - + Console Консоль - + Safe Area (Right Click to Select) Безопасная зона (Щелкните правой кнопкой мыши, чтобы выбрать) - + Field Guide Направляющая сетка - + Camera Stand View Стандартный вид с камеры - + 3D View 3D-просмотр - + Camera View Вид с камеры - + Freeze Заморозить - + Preview Предпросмотр - + Sub-camera Preview Предпросмотр суб-камеры - + Untitled Безымянный - + Scene: Сцена: - + :: Frame: :: Кадр: - - - + + + (Flipped) - + :: Level: :: Уровень: - + Level: Уровень: @@ -1441,17 +1547,17 @@ What do you want to do? Customize XSheet Toolbar - + Настроить панель инструментов Xsheet Command Bar - + Панель команд Customize Command Bar - + Настройка панели команд @@ -1506,185 +1612,185 @@ What do you want to do? ConvertPopup - + Level %1 already exists; skipped. Уровень %1 уже существует; пропуск. - + Converting %1 Конвертация %1 - + Converting level %1 of %2: %3 Конвертация уровня %1 из %2: %3 - + Level %1 has no frame; skipped. Уровень %1 не имеет кадров; пропуск. - + Unpainted tlv Неокрашенный tlv - + Unpainted tlv from non AA source Неокрашенный tlv из источника без AA - + Painted tlv from two images Окрашенный tlv из двух изображений - + Painted tlv from non AA source Окрашенный tlv из источника без АА - - + + Same as Painted То же что и окрашенный - + Create new palette Создать новую палитру - + Options Опции - + Convert Конвертировать - - - + + + Cancel Отмена - + Bg Color: Цвет заднего плана: - + Skip Existing Files Пропустить существующие файлы - + Remove dot before frame number Удалите точку перед номером кадра - + Convert... Конвертировать... - + File to convert: Файл для конвертации: - + Start: Старт: - + End: Конец: - + Save in: Сохранить в: - + File Name: Имя файла: - + File Format: Формат файла: - + Stroke Mode: Режим обводки: - + Centerline Ось - + Outline Контур - + Unpainted File Folder: Папка неокрашенного файла: - + Unpainted File Suffix: Суффикс неокрашенного файла: - + Apply Autoclose Применить Autoclose - + Save Backup to "nopaint" Folder Сохранить резервную копию в папку «nopaint» - + Append Default Palette Добавить палитру по умолчанию - + Remove Unused Styles from Input Palette Удаление неиспользуемых стилей из палитры ввода - + Keep Original Antialiasing Сохранять оригинальное сглаживание - + Add Antialiasing with Intensity: Добавить сглаживание с интенсивностью: - + Remove Antialiasing using Threshold: Удалить сглаживание с использованием порога: - + When activated, styles of the default palette ($TOONZSTUDIOPALETTE\cleanup_default.tpl) will be appended to the palette after conversion in @@ -1696,22 +1802,22 @@ before color designing. сохранить попытки по созданию стилей перед рисованием цветом. - + Image DPI DPI изображения - + Current Camera DPI Текущее разрешение камеры в DPI - + Custom DPI Пользовательское значение DPI - + Specify the policy for setting DPI of converted tlv. If you select the "Image DPI" option and the source image does not contain the dpi information, then the current camera dpi will be used. @@ -1722,103 +1828,103 @@ contain the dpi information, then the current camera dpi will be used. - + Mode: Режим: - + Antialias: Сглаживание: - + Palette: Палитра: - + Tolerance: Допуск: - + Dpi: DPI: - + Convert 1 Level Конвертировать 1 уровень - + Convert %1 Levels Конвертировать%1 уровней - - + + Level Уровень - + already exists; skipped уже существует; пропущено - + Generating level Генерирование уровня - + converted to tlv. конвертировано в tlv. - + Level %1 converted to TLV Format Уровень %1 конвертирован в формат TLV - + Warning: Level %1 NOT converted to TLV Format Внимание: Уровень %1 НЕ конвертирован в формат TLV - + Converted %1 out of %2 Levels to TLV Format Конвертировано %1 из%2 Уровни в формат TLV - + Warning: Can't read palette '%1' Внимание: не удается прочитать палитру "%1" - + No output filename specified: please choose a valid level name. Не указано имя выходного файла: выберите допустимое имя уровня. - + No unpainted suffix specified: cannot convert. Нет неокрашенного суффикса: нельзя конвертировать. - + Convert completed with %1 error(s) and %2 level(s) skipped Конвертирование выполнено с ошибкой %1 и %2 уровни пропущены - + Convert completed with %1 error(s) Конвертирование выполнено с ошибкой %1 - + %1 level(s) skipped Уровень %1 пропущен @@ -1826,7 +1932,7 @@ contain the dpi information, then the current camera dpi will be used. DVGui::ProgressDialog - + Loading "%1"... Загрузка "%1"... @@ -2095,12 +2201,12 @@ contain the dpi information, then the current camera dpi will be used. ExportCurvePopup - + Export Curve Экспорт кривой - + Export Экспорт @@ -2345,206 +2451,206 @@ contain the dpi information, then the current camera dpi will be used. Некоторые файлы, которые вы хотите разблокировать, в настоящее время открыты. Закройте их сначала. - + Folder: Папка: - + Open folder failed Не удалось открыть папку - + The input folder path was invalid. Недопустимый путь к папке ввода. - + Can't change file extension Не удалось расширение файла - + Can't set a drawing number Не удалось установить номер рисунка - + Can't rename. File already exists: Не удалось переименовать. Файл уже существует: - + Couldn't rename Не удалось переименовать - + Preview Screensaver Просмотр Screensaver - + Install Screensaver Установка Screensaver - + Load As Sub-xsheet Загрузить как Sub-xsheet - + Load Загрузить - + Rename Переименовать - + Convert to Painted TLV Конвертировать в окрашенный TLV - + Convert to Unpainted TLV Конвертировать в неокрашенный TLV - + Version Control Управление версиями - - + + Edit Редактировать - - + + Edit Frame Range... Изменить диапазон кадров... - - - + + + Put... Поместить... - - + + Revert Вернуть - - - - - + + + + + Get Получить - + Delete Удалить - + Get Revision... Пересмотреть... - + Unlock Разблокировать - - - + + + Edit Info Изменить инфо - + Revision History... Пересмотреть историю... - + Unlock Frame Range Разблокировать диапазон кадров - + Save Scene Сохранить сцену - + Scene name: Название сцены: - + There was an error copying %1 to %2 Произошла ошибка при копировании %1 в %2 - + Convert To Unpainted Tlv Конвертировать в неокрашенный TLV - - + + Warning: level %1 already exists; overwrite? Внимание: уровень %1 уже существует; перезаписать? - - + + Yes Да - - + + No Нет - + Done: All Levels converted to TLV Format Выполнено: все уровни конвертированы в формат TLV - + Convert To Painted Tlv Конвертировать в окрашенный TLV - + Done: 2 Levels converted to TLV Format Выполнено: 2 уровня, конвертированы в формат TLV - + New Folder Новая папка - + It is not possible to create the %1 folder. Не удалось создать папку %1. @@ -2600,18 +2706,18 @@ contain the dpi information, then the current camera dpi will be used. FileSelection - + Collecting assets... Сбор материалов... - - + + Abort Прервать - + Importing scenes... Импорт сцен... @@ -2632,20 +2738,20 @@ contain the dpi information, then the current camera dpi will be used. Filmstrip - - - - + + + + - No Current Level - - Нет текущего уровня - - + Level Strip Level Strip - + Level: Уровень: @@ -2653,30 +2759,53 @@ contain the dpi information, then the current camera dpi will be used. FilmstripFrameHeadGadget - + Click to Toggle Fixed Onion Skin Включить фиксированный Onion Skin - + Click / Drag to Toggle Onion Skin Клик/Перетащить Onion Skin - + Drag to Extend Onion Skin, Double Click to Toggle All Перетащите, чтобы расширить Onion Skin.Двойной клик, чтобы переключить все + + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + + Click to Move Shift & Trace Marker + + FilmstripFrames - + no icon нет значка - + Linear Линейный @@ -2684,56 +2813,56 @@ contain the dpi information, then the current camera dpi will be used. FlipBook - - + + Flipbook Flipbook - + The file name cannot be empty or contain any of the following characters:(new line) \ / : * ? " | Имя файла не может быть пустым или содержать любой из следующих символов: (новая строка) \ /: *? "| - + It is not possible to save because the selected file format is not supported. Это невозможно сохранить, потому что выбранный формат файла не поддерживается. - + File %1 already exists. Do you want to overwrite it? Файл «%1» уже существует. Хотите перезаписать его? - + It is not possible to save Flipbook content. Невозможно сохранить содержимое Flipbook. - + Saved %1 frames out of %2 in %3 Сохранено %1 кадр из %2 в %3 - + There are no rendered images to save. Нет отрендеренных изображений для сохранения. - - + + It is not possible to take or compare snapshots for Toonz vector levels. Невозможно получить или сравнить snapshots для векторных уровней Toonz. - + Rendered Frames :: From %1 To %2 :: Step %3 Рендер кадров :: От %1 до %2 :: Шаг %3 - + :: Shrink :: Сокращать @@ -2741,12 +2870,12 @@ Do you want to overwrite it? FlipbookPanel - + Safe Area (Right Click to Select) Безопасная зона (Щелкните правой кнопкой мыши, чтобы выбрать) - + Minimize Уменьшить @@ -2767,12 +2896,12 @@ Do you want to overwrite it? FrameHeadGadget - + Current Frame Текущий кадр - + Fixed Onion Skin Toggle Переключение фиксированной кальки @@ -2887,39 +3016,39 @@ Do you want to overwrite it? InbetweenDialog - - + + Inbetween промежуточные кадры автофазовка - + Linear Линейная - + Ease In Ease In - + Ease Out Ease Out - + Ease In / Ease Out Ease In / Ease Out - + Interpolation: Интерполяция: - + Cancel Отмена @@ -2983,6 +3112,92 @@ Do you want to overwrite it? + ItemInfoView + + + Bold + + + + + Italic + + + + + Ignore + + + + + Keep + + + + + Name: + Имя: + + + + Type: + Тип: + + + + Path: + Путь: + + + + Aspect Ratio: + + + + + Font: + + + + + Max Size: + + + + + No item selected. + + + + + Item + + + + + ItemListView + + + Add + Добавить + + + + Remove + Удалить + + + + Move Up + + + + + Move Down + + + + LayerFooterPanel @@ -3003,17 +3218,17 @@ Do you want to overwrite it? LayerHeaderPanel - + Preview Visbility Toggle All - + Camera Stand Visibility Toggle All Переключатель видимости камеры - + Lock Toggle All @@ -3152,158 +3367,158 @@ Do you want to create it? LevelSettingsPopup - - + + DPI: DPI: - - + + Premultiply Умножение - - + + White As Transparent Белый как прозрачный - - + + Add Antialiasing Добавить сглаживание - - + + Antialias Softness: Мягкость сглаживания: - - + + Subsampling: Субдискретизация: - + Level Settings Настройки уровня - + Scan Path: Путь сканирования: - + Forced Squared Pixel Принудительно квадратные пиксели - + Width: Ширина: - + Height: Высота: - + Use Camera DPI Использовать DPI камеры - + Camera DPI: Камера DPI: - + Image DPI: DPI изображения: - + Resolution: Разрешение: - + Image DPI DPI изображения - + Custom DPI Пользовательское значение DPI - + Name && Path Имя и путь - + Name: Имя: - + Path: Путь: - + Resolution Разрешение - + DPI && Resolution DPI и разрешение - + Scan level Уровень сканирования - + Toonz Vector level Векторный уровень Toonz - + Toonz Raster level Растровый уровень Toonz - + Raster level Растровый уровень - + Mesh level Уровень меша - + Palette level Уровень палитры - + Sound Column Столбец со звуковой дорожкой - + The file %1 is not a sound level. Файл %1 не является уровнем звука. @@ -3415,32 +3630,32 @@ Do you want to create it? LineTestPane - + Preview Предпросмотр - + Untitled Безымянный - + Scene: Сцена: - + :: Frame: :: Кадр: - + :: Level: :: Уровень: - + Level: Уровень: @@ -3586,6 +3801,14 @@ Please use the frame numbers for reference. + LoadBoardPresetFilePopup + + + Load Clapperboard Settings Preset + + + + LoadColorModelPopup @@ -3606,12 +3829,12 @@ Please use the frame numbers for reference. LoadCurvePopup - + Load Curve Загрузить кривую - + Load Загрузить @@ -3627,42 +3850,42 @@ Please use the frame numbers for reference. LoadImagesPopup - + Load Images Загрузить изображения - + Append Добавить - + From: От: - + To: До: - + Step: Шаг: - + Shrink: Сокращение: - + Load Загрузить - + Load / Append Images Загрузка / Добавление изображений @@ -3944,352 +4167,352 @@ Please use the frame numbers for reference. Безымянный - + Cleanup Очистка - + PltEdit Палитра - + InknPaint InknPaint - + Xsheet Xsheet - + About OpenToonz О программе - + Close Закрыть - + Cannot delete Не удается удалить - + &New Scene &Новая сцена - + &Load Scene... &Загрузить сцену... - + &Save Scene &Сохранить сцену - + &Save Scene As... &Сохранить сцену как... - + &Save All &Сохранить все - + &Revert Scene &Откатить сцену - + &Load Folder... &Загрузить папку ... - + &Load As Sub-xsheet... &Загрузить как Sub-xsheet... - + &Open Recent Scene File &Открыть предыдущую сцену - + &Open Recent Level File &Открыть предыдущий уровень - + &Clear Recent Scene File List &Очистить список предыдущих сцен - + &Clear Recent level File List &Очистить список предыдущих уровней - + &New Level... &Новый уровень... - + &New Vector Level &Новый векторный уровень - + New Vector Level Новый векторный уровень - + &New Toonz Raster Level &Новый растровый уровень Toonz - + New Toonz Raster Level Новый растровый уровень Toonz - + &New Raster Level &Новый растровый уровень - + New Raster Level Новый растровый уровень - + &Load Level... &Загрузить уровень... - + &Save Level &Сохранить уровень - + &Save All Levels &Сохранить все уровни - + &Save Level As... &Сохранить уровень как... - + &Export Level... &Экспортировать уровень... - + &Convert File... &Конвертировать файл... - + &Save Palette As... &Сохранить палитру как... - + &Save Palette &Сохранить палитру - + &Load Color Model... &Загрузить цветовую модель... - + &Import Magpie File... &Импорт файла Magpie... - + &New Project... &Новый проект... - + &Project Settings... &Настройки проекта... - + &Save Default Settings &Сохранить настройки по умолчанию - + &Output Settings... &Настройки вывода ... - + &Preview Settings... &Настройки предпросмотра... - + &Render &Рендер - + &Fast Render to MP4 &Рендер в MP4 - + &Preview &Предпросмотр - + &Export Soundtrack &Экспорт звуковой дорожки - + &Save Previewed Frames &Сохранить кадры предпросмотра - + &Regenerate Preview &Регенерировать предпросмотр - + &Regenerate Frame Preview &Регенерировать предпросмотр кадра - + &Clone Preview &Клонировать предпросмотр - + &Freeze//Unfreeze Preview &Заморозить//разморозить предпросмотр - + Freeze Preview Заморозить предпросмотр - + Unfreeze Preview Разморозить предпросмотр - + &Save As Preset &Сохранить как пресет - + &Preferences... &Настройки программы... - + &Configure Shortcuts... &Настройка горячих клавиш... - + &Print Xsheet &Экспорт Xsheet в HTML - + Run Script... Запустить скрипт... - + Open Script Console... Открыть командную строку ... - + &Print Current Frame... &Распечатать текущий кадр... - + &Quit &Выйти - + Reload qss Обновить qss - + &Load Recent Image Files &Загрузить предыдущие файлы изображений - + &Clear Recent Flipbook Image List &Очистить список предыдущих изображений Flipbook - + Preview Fx Предпросмотр Fx - + &Select All &Выбрать все - + &Invert Selection &Обратить выделенное - + &Undo &Отменить - + &Redo &Повторить - + &Cut &Вырезать - + &Copy &Копировать @@ -4298,187 +4521,192 @@ Please use the frame numbers for reference. &Вставить - + &Merge &Слияние - + &Paste Into &Поместить в - + &Paste Color && Name &Вставить цвет и имя - + Paste Color Вставить цвет - + Paste Name Вставить имя - + Get Color from Studio Palette Взять цвет из Studio Palette - + Toggle Link to Studio Palette Переключить линк на Studio Palette - + Remove Reference to Studio Palette Удалить референс на Studio Palette - + &Delete &Удалить - + &Insert &Вставить - + &Group &Сгруппировать - + &Ungroup &Разгруппировать - + &Bring to Front &На передний план - + &Bring Forward &На порядок выше - + &Send Back &На порядок ниже - + &Send Backward &На задний план - + &Enter Group &Войти в группу - + &Exit Group &Выйти из группы - + &Remove Vector Overflow &Удалить векторные излишки - + &Touch Gesture Control &Управление сенсорными жестами - + &Define Scanner... &Определить сканер... - + &Scan Settings... &Настройки сканера... - + &Scan &Сканирование - + &Autocenter... &Автоцентр... - + &Set Cropbox &Установить область обрезки - + &Reset Cropbox &Сбросить область обрезки - + &Cleanup Settings... &Настройки очистки... - + &Preview Cleanup &Просмотр очистки - + &Camera Test &Тестирование камеры - + &Opacity Check &Opacity Check - + &Cleanup &Очистка - + &Camera Capture... &Захват камеры... - + &Add Frames... &Добавить кадры... - + &Renumber... &Пересчитать... - + &Replace Level... &Заменить уровень ... - + &Revert to Cleaned Up &Возврат к очистке - + + Separate Colors... + + + + Animate Tool Инструмент анимирования @@ -4487,814 +4715,824 @@ Please use the frame numbers for reference. &Возврат к последней сохраненной версии - + &Paste Insert &Вставить вставку - + &Paste Insert Above/After - + &Insert Above/After - + &Expose in Xsheet &Экспонировать в Xsheet - + &Display in Level Strip &Отобразить в Level Strip - + &Level Settings... &Настройки уровня... - + Adjust Levels... Коррекция цветовых уровней... - + Adjust Thickness... Отрегулировать толщину... - + &Antialias... &Сглаживание... - + &Binarize... &Бинаризация... - + &Brightness and Contrast... &Яркость и контрастность... - + &Color Fade... &Color Fade... - + &Capture &Захват - + &Canvas Size... &Размер холста... - + &Info... &Инфо... - + &View... &Вид... - + &Remove All Unused Levels &Удалить все неиспользуемые в сцене уровни - + &Replace Parent Directory... &Заменить родительский каталог ... - + &Scene Settings... &Настройки сцены... - - + + &Camera Settings... &Настройки камеры... - + &Open Sub-xsheet &Открыть Sub-xsheet - + &Close Sub-xsheet &Закрыть Sub-xsheet - + Explode Sub-xsheet Разбить Sub-xsheet - + Collapse Коллапс - + Toggle Edit in Place Переключить Редактировать на месте - + &Save Sub-xsheet As... &Сохранить Sub-xsheet как... - + Resequence Пересчитать секвенцию - + Clone Sub-xsheet Клонировать Sub-xsheet - + &Apply Match Lines... &Применить Match Lines... - + &Merge Tlv Levels... &Объединить уровни Tlv ... - + &Delete Match Lines &Удалить Match Lines - + &Delete Lines... &Удалить линии... - + &Merge Levels &Объединить уровни - + &New FX... &Новый FX... - + &New Output &Новый вывод - + &Edit FX... &Редактировать FX... - + Insert Frame Вставить кадр - + Remove Frame Удалить кадр - + Insert Multiple Keys Вставить несколько ключей - + Remove Multiple Keys Удаление нескольких ключей - + Remove Empty Columns Удалить пустые столбцы - + &Reverse &Обратить - + &Swing &Добавить в обратном порядке - + &Random &Случайно - + &Autoexpose &Автоэкспонирование - + &Repeat... &Повторение... - + &Reset Step &Сбросить шаг - + &Increase Step &Увеличить шаг - + &Decrease Step &Уменьшить шаг - + &Step 2 &Шаг 2 - + &Step 3 &Шаг 3 - + &Step 4 &Шаг 4 - + &Each 2 &Каждые 2 - + &Each 3 &Каждые 3 - + &Each 4 &Каждые 4 - + &Roll Up думаю, так будет понятнее, чем "все кадры кроме первого наверх" &Первый вниз - + &Roll Down &Последний наверх - + &Time Stretch... &Растяжение времени... - + &Duplicate Drawing &Дублировать рисунок - + &Autorenumber &Автопересчет - + &Clone &Клонировать - + Drawing Substitution Forward Заправка чертежа вперед - + Drawing Substitution Backward Заправка чертежа назад - + Similar Drawing Substitution Forward Заправка аналогичных чертежей вперед - + Similar Drawing Substitution Backward Заправка аналогичных чертежей назад - + 1's по 1 - + 2's по 2 - + 3's по 3 - + 4's по 4 - + &Fill In Empty Cells &Заполнить пустые ячейки - + &Set Key &Установить ключ - + &Camera Box &Граница камеры - + &Table &Таблица - + &Field Guide &Направляющая сетка - + &Raster Bounding Box &Растровая граница - + &Field Guide in Capture Window &Направляющая сетка в окне захвата - + &Safe Area ?? &Безопасная зона - + &Camera BG Color &Камера Цвет фона - + &Guide &Ориентир - + &Ruler &Линейка - + &Transparency Check &Проверка прозрачности - + &Ink Check &Проверка штриха - + &Ink#1 Check &Проверка штриха#1 - + &Paint Check &Проверка цвета - + Inks &Only Только &линии - + &Fill Check &Проверка заполнения - + &Black BG Check &На чёрном фоне - + &Gap Check &Проверка замкнутости - + Shift and Trace Сдвинуть и калькировать - + Edit Shift Редактировать сдвиг - + No Shift Без сдвига - + Reset Shift Сбросить сдвиг - + &Visualize Vector As Raster &Отображать вектор как растр - + &Histogram &Гистограмма - + Link Flipbooks Link Flipbooks - + Play Воспроизведение - + Loop Loop - + Pause Pause - + First Frame Первый кадр - + Last Frame Последний кадр - + Previous Frame Предыдущий кадр - + Next Frame Следующий кадр - + Next Drawing Следующий рисунок - + Prev Drawing Предыдущий рисунок - + Next Step Следующий шаг - + Prev Step Предыдущий шаг - + Red Channel Красный канал - + Green Channel Зеленый канал - + Blue Channel Голубой канал + + Flip Viewer Horizontally + + + Matte Channel Матовый канал - + Red Channel Greyscale Красный канал в оттенках серого - + Green Channel Greyscale Зеленый канал в оттенках серого - + Blue Channel Greyscale Голубой канал в оттенках серого - + Compare to Snapshot Сравнить с Snapshot - + Toggle Autofill on Current Palette Color Переключить автозаливку на текущий цвет палитры - + &Lock Room Panes &Заблокировать Room Panes - + &Export &Экспортировать - + &File Browser &Браузер файлов - + &Flipbook &Flipbook - + &Function Editor &Редактор функций - + &Level Strip &Level Strip - + &Palette &Палитра - + &Palette Gizmo &Палитра Gizmo - + &Delete Unused Styles &Удалить неиспользуемые стили - + &Tasks &Задания - + &Batch Servers &Пакетные серверы - + &Message Center &Центр сообщений - + &Color Model &Цветная модель - + &Studio Palette &Палитра Studio - + &Schematic &Схемы - + &Cleanup Settings &Настройки очистки - + &Scene Cast &Состав сцены - + &Style Editor &Редактор стилей - + &Toolbar &Панель инструментов - + &Tool Option Bar &Панель настройки инструментов - + &Viewer &Просмотрщик - + &LineTest Capture &LineTest захват - + &LineTest Viewer &LineTest просмотрщик - + &Xsheet &Xsheet - + + &Timeline + + + + &ComboViewer &ComboViewer - + &History &История - + Record Audio Запись аудио - + &Reset to Default Rooms &Сбросить вкладки по умолчанию - + Toggle Maximize Panel Переключить максимизацию панелей - + Toggle Main Window's Full Screen Mode Переключить главное окно в полноэкранный режим - + &About OpenToonz... &О программе... - + &Startup Popup... &Стартовое окно... - + &Blend colors &Смешивание цветов - + Onion Skin Toggle Переключение видимости кальки - + Zero Thick Lines Линии нулевой толщины - + Toggle Cursor Size Outline Переключить размер курсора контура - + Duplicate Дублировать - + Show Folder Contents Показать содержимое папки - + Convert... Конвертировать... - + Collect Assets Сбор активов - + Import Scene Импортировать сцену - + Export Scene... Экспортировать сцену... - + Convert to Vectors... Конвертировать в вектор... - + Tracking... Трекинг... - + Remove Level Удалить уровень - + Add As Render Task Добавить как задачу рендеринга - + Add As Cleanup Task Добавить как задачу очистки @@ -5303,32 +5541,32 @@ Please use the frame numbers for reference. Выделить все ключи в этом ряду - + Select All Keys in this Column Выделить все ключи в этом столбце - + Select All Keys Выделить все ключи - + Select All Following Keys Выделить все следующие ключи - + Select All Previous Keys Выделить все предыдущие ключи - + Select Previous Keys in this Column Выделить предыдущие ключи в этом столбце - + Select Following Keys in this Column Выделить все следующие ключи в этом столбце @@ -5341,207 +5579,247 @@ Please use the frame numbers for reference. Выделить все следующие ключи в этом ряду - + &Reload &Перезагрузить - + &Toggle Edit In Place &Редактировать на месте - + New Note Level Новый уровень заметок - + &Apply Lip Sync Data to Column &Применить данные липсинка к столбцу - + Toggle XSheet Toolbar Показать/скрыть панель Xsheet - + Reframe with Empty Inbetweens... Перекадрировать с пустыми промежутками... - + Auto Input Cell Number... Автоматический ввод номера ячейки... - + &Paste Numbers &Вставлять номер видео - + Alpha Channel Альфа-канал - + &Command Bar &Панель команд - + Toggle Current Time Indicator Скрыть/показать индикатор кадра - + Vectors to Toonz Raster Конвертировать вектор в Toonz растр - + Replace Vectors with Simplified Vectors Заменить вектора упрощенными векторами - + Select All Keys in this Frame Выделить все ключи в этом кадре - + Select Previous Keys in this Frame Выделить все предыдущие ключи перед кадром - + Select Following Keys in this Frame Выделить все последующие ключи после кадра - + Invert Key Selection Инвертировать выбор ключей - + Set Acceleration Установка ускорения - + Set Deceleration Установка замедления - + Set Constant Speed Установить постоянную скорость - + Reset Interpolation Сбросить интерполяцию - + + Linear Interpolation + + + + + Speed In / Speed Out Interpolation + + + + + Ease In / Ease Out Interpolation + + + + + Ease In / Ease Out (%) Interpolation + + + + + Exponential Interpolation + + + + + Expression Interpolation + + + + + File Interpolation + + + + + Constant Interpolation + + + + Fold Column Свернуть столбцы - + Show This Only Показать только это - + Show Selected Показать выбранные - + Show All Показать все - + Hide Selected Скрыть выбранные - + Hide All Скрыть все - + Toggle Show/Hide Переключить: Показать/Спрятать - + ON This Only ВКЛ только это - + ON Selected ВКЛ выбранные - + ON All ВКЛ все - + OFF All ВЫКЛ все - + OFF Selected ВЫКЛ выбранные - + Swap ON/OFF Переключить ВКЛ/ВЫКЛ - + Lock This Only Заблокировать это только - + Lock Selected Заблокировать выбранные - + Lock All Заблокировать все - + Unlock Selected Разблокировать выбранные - + Unlock All Разблокировать все - + Swap Lock/Unlock Переключатель Блокировать/Разблокировать - + Hide Upper Columns Скрыть верхние столбцы @@ -5550,512 +5828,511 @@ Please use the frame numbers for reference. Инструмент редактирования - + Selection Tool Инструмент выделения - + Brush Tool Кисть - + Geometric Tool Геометрический инструмент - + Type Tool Инструмент шрифта - + Fill Tool Заливка - + Paint Brush Tool Инструмент покраски - + Eraser Tool Ластик - + Tape Tool Скотч - + Style Picker Tool Пипетка - + RGB Picker Tool Инструмент RGB пипетка - + Control Point Editor Tool Редактор контрольных точек - + Pinch Tool Щипок - + Pump Tool Насос - + Magnet Tool Магнит - + Bender Tool Клещи - + Iron Tool Утюг - + Cutter Tool Нож - + Skeleton Tool Скелет - + Tracker Tool Трекер - + Hook Tool Крюк - + Zoom Tool Лупа - + Rotate Tool Поворот - + Hand Tool Рука - + Plastic Tool Plastic Tool - + Ruler Tool Рулетка - + Finger Tool Палец - + Zoom In Приблизить - + Zoom Out Отдалить - + Reset View Вид по умолчанию - + Fit to Window По размеру окна - + Actual Pixel Size Фактический пиксельный размер - Flip Viewer Horiontally - Повернуть просмотр горизонтально + Повернуть просмотр горизонтально - + Flip Viewer Vertically Повернуть просмотр вертикально - + Show//Hide Full Screen Показать // Скрыть полный экран - + Full Screen Mode Полноэкранный режим - + Exit Full Screen Mode Выход из полноэкранного режима - + Refresh Folder Tree Обновить дерево папок - + Refresh Обновить - + Global Key Глобальный ключ - + Brush size - Increase max Размер кисти - Увеличить макс - + Brush size - Decrease max Размер кисти - Уменьшение макс - + Brush size - Increase min Размер кисти - Увеличить мин - + Brush size - Decrease min Размер кисти - Уменьшение мин - + Brush hardness - Increase Жесткость кисти - увеличение - + Brush hardness - Decrease Жесткость кисти - уменьшение - + SnapSensitivity Чувствительность - + Auto Group Автогруппа - + Break sharp angles Разрыв острых углов - + Frame range Диапазон кадров - + Inverse kinematics Инверсная кинематика - + Invert Инвертировать - + Manual Вручную - + Onion skin Калька - + Orientation Ориентация - + Pencil Mode Режим карандаша - + Preserve Thickness Сохранять толщину - + Pressure Sensitivity Чувствительность к давлению - + Segment Ink Сегмент Ink - + Selective Избирательно - + Brush Tool - Draw Order Кисть - порядок рисования - + Smooth Гладкий - + Snap Snap - + Auto Select Drawing Автоматический выбор рисунка - + Auto Fill Автозаливка - + Join Vectors объединить векторы - + Show Only Active Skeleton Показать только активный скелет - + Brush Preset Пресет кисти - + Geometric Shape Геометрическая форма - + Geometric Edge Геометрический край - + Mode Режим - + Mode - Areas Режим - Области - + Mode - Lines Режим - Линии - + Mode - Lines & Areas Режим - Линии и Области - + Type Тип - + Type - Normal Тип - обычный - + Type - Rectangular Тип - Прямоугольный - + Type - Freehand Тип - от руки - + Type - Polyline Тип - Полилиния - + TypeTool Font Шрифт - + TypeTool Size Размер шрифта - + TypeTool Style Стиль шрифта - + Active Axis Активная ось - + Active Axis - Position Активная ось - расположение - + Active Axis - Rotation Активная ось - вращение - + Active Axis - Scale Активная ось - масштаб - + Active Axis - Shear Активная ось - сдвиг - + Active Axis - Center Активная ось - центр - + Active Axis - All Активные оси - все - + Build Skeleton Mode Режим создания скелета - + Animate Mode Режим анимации - + Inverse Kinematics Mode Режим инверсной кинематики - + None Pick Mode Объектов выделения - нет - + Column Pick Mode Режим выбора столбца - + Pegbar Pick Mode Режим выбора Pegbar - + Pick Screen Кликнуть по экрану - + Create Mesh Создать полисетку - + Fill Tool - Autopaint Lines Заливка - авторисовка линий - + Fill Tool - Areas Заливка - Области - + Fill Tool - Lines Заливка - Линиии - + Style Picker Tool - Areas Инструмент выбора стиля - Области - + Style Picker Tool - Lines Инструмент выбора стиля - Линии - + Toggle FX/Stage schematic Переключение Схемы Fx @@ -6268,64 +6545,64 @@ N.B. Duplicated commands will be ignored. Only the last one will appear in the m MeshifyPopup - + A level with the preferred path "%1" already exists. What do you want to do? Уровень с предпочтительным путем «%1» уже существует. Что вы хотите сделать? - + Delete the old level entirely Полностью удалить старый уровень - + Keep the old level and overwrite processed frames Сохранить старый уровень и перезаписать обработанные кадры - + Choose a different path (%1) Выберите другой путь (%1) - + Create Mesh Создать полисетку - + Mesh Edges Length: Длина кромки полисетки: - + Rasterization DPI: Растеризация DPI: - + Mesh Margin (pixels): Край полисетки (пиксели): - + Apply Применить - + Mesh Creation in progress... Создание полисетки выполняется... - + Current selection contains mixed image and mesh level types Текущий выбор содержит смешанные изображения и типы уровней полисетки - + Current selection contains no image or mesh level types Текущий выбор не содержит типов изображений или типов полисетки @@ -6367,7 +6644,7 @@ What do you want to do? MyViewFinder - + Camera is not available Камера недоступна @@ -6375,344 +6652,366 @@ What do you want to do? OutputSettingsPopup - + Preview Settings Настройки предпросмотра - + Output Settings Настройки вывода - + Camera Settings Настройки камеры - + File Settings Настройки файла - + Options Опции - + Use Sub-Camera Использовать суб-камеру - + Apply Shrink to Main Viewer ? Применить Shrink к Main Viewer - + Other Settings Другие настройки - + Render Рендер - + Add Добавить - + Remove Удалить - + Do stereoscopy Сделать стереоскопию - + Standard Простое - + Improved Улучшенный - + High Высокий - + Triangle filter Треугольный фильтр - + Mitchell-Netravali filter Фильтр Митчелла-Нетравали - + Cubic convolution, a = .5 Кубическая свертка, a = .5 - + Cubic convolution, a = .75 Кубическая свертка, a = .75 - + Cubic convolution, a = 1 Кубическая свертка, a = 1 - + Hann window, rad = 2 ? Hann window, rad = 2 - + Hann window, rad = 3 Hann window, rad = 3 - + Hamming window, rad = 2 Hamming window, rad = 2 - + Hamming window, rad = 3 Hamming window, rad = 3 - + Lanczos window, rad = 2 Lanczos window, rad = 2 - + Lanczos window, rad = 3 Lanczos window, rad = 3 - + Gaussian convolution Гауссова свертка - + Closest Pixel (Nearest Neighbor) Ближайший пиксель (ближайший соседний) - + Bilinear Билинейный - + 8 bit 8 бит - + + Add Clapperboard + + + + + Edit Clapperboard... + + + + 16 bit 16 бит - + Odd (NTSC) Odd (NTSC) - + Even (PAL) Even (PAL) - - - + + + None Ничего - + Fx Schematic Flows Схемы Fx - + Fx Schematic Terminal Nodes Fx Схематические терминальные узлы - + + Save current output settings. +The parameters to be saved are: +- Camera settings +- Project folder to be saved in +- File format +- File options +- Resample Balance +- Channel width + + + + Single Один - + Half Половина - + All Все - + Large Большой - + Medium Средний - + Small Маленький - + Presets: Предустановки: - + Output Camera: Выходная камера: - + Frame Start: ? Начальный кадр: - + End: Конец: - + Step: Шаг: - + Shrink: Сокращение: - + Save in: Сохранить в: - + Name: Имя: - + Resample Balance: Ресемплировать баланс: - + Channel Width: Ширина канала: - + Dedicated CPUs: Выделенные процессоры: - + Render Tile: Render Tile: - + Gamma: Гамма: - + Dominant Field: Доминантное поле: - + Frame Rate (linked to Scene Settings): Частота кадров (связанная с настройками сцены): - + Stretch from FPS: Растяжка по FPS: - + To: До: - + Multiple Rendering: Многократный рендеринг: - + Camera Shift: Сдвиг камеры: - + Add preset Добавить предустановку - + Enter the name for the output settings preset. Введите имя для заданных параметров вывода. - + Add output settings preset Добавить предустановку настроек вывода - + <custom> <пользовательский> - + Remove preset Удалить пресет - - - + + + Warning Предупреждение @@ -6720,7 +7019,7 @@ What do you want to do? OverwriteDialog - + Level "%1" already exists. What do you want to do? @@ -6809,285 +7108,285 @@ Do you want to overwrite it? PencilTestPopup - + No frame id Нет - + Camera Capture Захват камеры - + Refresh Обновить - + File Файл - + Options Опции - + Save images as they are captured Сохранение изображений при их захвате - + Image adjust Настройка изображения - + Upside down Вверх ногами - + Capture white BG Захват белого фона - + Display Отображение - + Show onion skin Показать кальку - + Load Selected Image Загрузить выбранное изображение - + Interval timer Интервальный таймер - + Use interval timer Использовать интервальный таймер - - + + Capture [Return key] Захват [Return/Enter] - + Close Закрыть - + Subfolder Подпапка - + Next Level Следующий уровень - + Previous Level Предыдущий уровень - + Color Цвет - + Grayscale Оттенки серого - + Black & White Черно-белый - + Video Capture Filter Settings... Настройки фильтра видеозахвата... - + Camera: Камера: - + Resolution: Разрешение: - + Save In: Сохранить в: - + Name: Имя: - + Frame: Кадр: - + File Type: Тип файла: - + Color type: Тип цвета: - - - - - + + + + + UNDEFINED WARNING НЕОПРЕДЕЛЕННОЕ ПРЕДУПРЕЖДЕНИЕ - + The level is not registered in the scene, but exists in the file system. Уровень не загружен в текущую сцену, но файл существует. - + WARNING : Image size mismatch. The saved image size is %1 x %2. Предупреждение: несоответствие размера изображения. Размер сохраненного изображения%1 x %2. - - - - + + + + WARNING Предупреждение - - + + Frame %1 exists. Кадр %1 существует. - - + + Frames %1 exist. Кадры %1 существуют. - - + + OVERWRITE 1 of ПЕРЕЗАПИСАТЬ 1 из - - + + ADD to ДОБАВИТЬ - - + + %1 frame %1 кадр - - + + %1 frames %1 кадров - + The level will be newly created. Уровень будет вновь создан. - + NEW НОВЫЙ - + The level is already registered in the scene. Этот уровень уже загружев в сцену. - + NOTE : The level is not saved. ПРИМЕЧАНИЕ : уровень не сохранен. - + WARNING : Failed to get image size of the existing level %1. ВНИМАНИЕ : получить размер изображения уровня %1 не удалось. - + WARNING : Image size mismatch. The existing level size is %1 x %2. ВНИМАНИЕ: несоответствие размера изображения. Существующий размер уровня %1 x %2. - + WARNING : Level name conflicts. There already is a level %1 in the scene with the path %2. ВНИМАНИЕ: конфликт имен уровней. В сцене уже есть уровень %1. Существующий путь к файлу уровня %2. - + WARNING : Image size mismatch. The size of level with the same name is is %1 x %2. ВНИМАНИЕ: несоответствие размера изображения. Размер уровня с тем же именем — %1 x %2. - + WARNING : Level path conflicts. There already is a level with the path %1 in the scene with the name %2. ВНИМАНИЕ : повторяющийся путь к файлу. В сцене уже есть уровень из %1 под именем %2. - + WARNING : Image size mismatch. The size of level with the same path is %1 x %2. @@ -7106,104 +7405,104 @@ WARNING : Image size mismatch. The size of level with the same path is %1 x %2.< Яркость: - + BG reduction: Редукция фона: - + Opacity(%): Непрозрачность (%): - + Interval(sec): Интервал(сек): - + No camera found Камера не найдена - + - Select camera - - Выбрать камеру - - - + + No image selected. Please select an image in the Xsheet. Изображения не выбраны. Выберите изображение в Xsheet. - + The selected image is not in a raster level. Выбранное изображение не находится на уровне растра. - + The selected image size does not match the current camera settings. Выбранный размер изображения не соответствует текущим настройкам камеры. - - + + Start Capturing [Return key] Запуск захвата [Ключ возврата] - + Stop Capturing [Return key] Остановить захват [Ключ возврата] - + No level name specified: please choose a valid level name Имя уровня не определено: выберите допустимое имя уровня - + Folder %1 doesn't exist. Do you want to create it? Папки %1 не существует. Вы хотите создать ее? - + Unable to create Не удалось создать - + The level name specified is already used: please choose a different level name. Указанное имя уровня уже используется: выберите другое имя уровня. - + The save in path specified does not match with the existing level. Указанный путь сохранения не соответствует существующему уровню. - - + + The captured image size does not match with the existing level. Размер захваченного изображения не соответствует существующему уровню. - - + + File %1 does exist. Do you want to overwrite it? Файл «%1» уже существует. Хотите перезаписать его? - + Failed to load %1. Не удалось загрузить %1. @@ -7211,135 +7510,135 @@ Do you want to overwrite it? PencilTestSaveInFolderPopup - + Create the Destination Subfolder to Save Создать папку назначения для сохранения - + Set As Default Установить по умолчанию - + Set the current "Save In" path as the default. Сделать текущий путь расположения по умолчанию. - + Create Subfolder Создать подпапку - + Infomation точно не "Info R mation" ? Информация - + Subfolder Name Имя подпапки - + Auto Format: Автоформат: - + Show This on Launch of the Camera Capture Показывать это окно при запуске захвата камеры - + Save Scene in Subfolder Сохранить сцену в подпапке - + OK OK - + Cancel Отмена - + C- + Sequence + Scene C- + Секвенция + Сцена - + Sequence + Scene Секвенция + Сцена - + Episode + Sequence + Scene Эпизод + Секвенция + Сцена - + Project + Episode + Sequence + Scene Проект + Эпизод + Секвенция + Сцена - + Save the current scene in the subfolder. Set the output folder path to the subfolder as well. Сохранить текущую сцену во вложенной папке. Также задайте путь к папке вывода на вложенную папку. - + Save In: Сохранить в: - + Project: Проект: - + Episode: Эпизод: - + Sequence: Секвенция: - + Scene: Сцена: - + Subfolder Name: Имя подпапки: - + Subfolder name should not be empty. Имя подпапки не должно быть пустым. - + Subfolder name should not contain following characters: * . " / \ [ ] : ; | = , Имя подпапки не должно содержать следующих символов: *. "/ \ []:; | =, - + Folder %1 already exists. Папка %1 уже существует. - + It is not possible to create the %1 folder. Не удалось создать папку %1. @@ -7347,17 +7646,17 @@ Set the output folder path to the subfolder as well. PltGizmoPopup - + Palette Gizmo Палитра Gizmo - + Blend Blend - + Fade Затухание @@ -7370,42 +7669,42 @@ Set the output folder path to the subfolder as well. Zero Matte - + Full Alpha Непрозрачный - + Zero Alpha Прозрачный - + Scale (%) Масштаб (%) - + Shift (value) Shift (значение) - + Value Значение - + Saturation Насыщенность - + Hue Hue - + Alpha Альфа @@ -7414,12 +7713,12 @@ Set the output folder path to the subfolder as well. Matte - + Fade to Color Fade to Color - + Color Цвет @@ -7427,199 +7726,200 @@ Set the output folder path to the subfolder as well. PreferencesPopup - + New Level Format Формат нового уровня - + Assign the new level format name: Назначьте имя формата нового уровня: - + New Format Новый формат - + Numpad keys are assigned to the following commands. Is it OK to release these shortcuts? Клавиши Numpad назначаются следующим командам. Хотите их изменить? - + OK OK - + Cancel Отмена - + Preferences Настройки программы - + General Общие - + Use Default Viewer for Movie Formats Использовать средство просмотра по умолчанию для форматов видео - + Minimize Raster Memory Fragmentation * Минимизировать фрагментацию растровой памяти * - + Save Automatically Сохранять автоматически - + Automatically Save the Scene File Сохранять файл сцены - + Automatically Save Non-Scene Files Сохранять файлы без сцены - + Show Startup Window when OpenToonz Starts Показывать стартовое окно при запуске OpenToonz - + Replace Toonz Level after SaveLevelAs command Заменять уровень Toonz после команды "Сохранить уровень как" - + Backup Animation Levels when Saving Делать резервные копии уровней при сохранении - + Show Info in Rendered Frames Показывать информацию в отрендереных кадрах - + Watch File System and Update File Browser Automatically Автоматически просматривать файловую систему и обновлять браузер файлов - + My Documents/OpenToonz* Мои Документы/OpenToonz* - + Desktop/OpenToonz* Рабочий стол/OpenToonz* - + Stuff Folder* Папка Stuff* - + Custom* 3 файла с звёздочкой * выше решил не переводить другое* - + Custom Project Path(s): Пользовательский путь(и) проекта: - + Advanced: Multiple paths can be separated by ** (No Spaces) Дополнительно: несколько путей могут быть разделены ** (Нет пробелов) - - - - - + + + + + + * Changes will take effect the next time you run Toonz * Изменения вступят в силу после перезапуска OpenToonz - + Interface Интерфейс - + All imported images will use the same DPI Все импортированные изображения будут использовать один и тот же DPI - + Move Current Frame by Clicking on Xsheet / Numerical Columns Cell Area Переместить текущий кадр, нажав на ячейку Xsheet / числовую область ячейки столбца - + Show Raster Images Darken Blended - + Color Calibration using 3D Look-up Table * Коррекция цвета с помощью 3D-таблицы поиска * - + Antialiased Region Boundaries Границы области с сглаживанием - + Down Arrow at End of Level Strip Creates a New Frame Стрелка вниз в конце Level Strip создает новый кадр - + Enable auto-stretch frame Заполнение пустых кадров - + Show Cursor Size Outlines Показать форму кисти - + Expand Function Editor Header to Match Xsheet Toolbar Height* Развернуть заголовок Function Editor, чтобы соответствовать высоте панели инструментов XSheet * - + Open Flipbook after Rendering Открыть Flipbook после рендеринга - + Enable Actual Pixel View on Scene Editing Mode Включить реальный пиксельный просмотр в режиме редактирования сцены - + Display Level Name on Each Marker Отображать имя уровня на каждом маркере @@ -7629,17 +7929,17 @@ Is it OK to release these shortcuts? Показать растровые изображения Darken Blended in Camstand View - + Show "ABC" Appendix to the Frame Number in Xsheet Cell Показывать «ABC» суффикс к номеру кадра в ячейке Xsheet - + Visualization Визуализация - + Show Lines with Thickness 0 Показать линии с нулевой толщиной @@ -7648,503 +7948,547 @@ Is it OK to release these shortcuts? Сглаженные границы областей - + Loading Загрузка - + Expose Loaded Levels in Xsheet Экспонировать загруженные уровни в Xsheet - + Create Sub-folder when Importing Sub-xsheet Создавать подпапки при импорте Sub-xsheet - + Use Camera DPI for All Imported Images Применять разрешение камеры ко всем импортированным изображениям - + Automatically Remove Scene Number from Loaded Level Name Автоматически удалять номер сцены из имени загруженного уровня - + Edit Правка - + Import/Export Импорт/Экспорт - + Drawing Рисунок - + DPI: DPI: - + New Levels Default to the Current Camera Size Новые уровни по умолчанию текущего разрешения камеры - + Keep Original Cleaned Up Drawings As Backup Сохранять оригинальные очищенные рисунки в качестве резервной копии - + Multi Layer Style Picker : Switch Levels by Picking Многослойная пипетка: Переключение уровней путем выбора - + Use the TLV Savebox to Limit Filling Operations Используйте команду «Сохранить в TLV» для ограничения заливки - + Minimize Savebox after Editing Минимизировать Savebox после правки - + + Saving + + + + Use Numpad and Tab keys for Switching Styles Использовать клавиши Numpad и Tab для переключения стилей - + Keep fill when using "Replace Vectors" command Сохранять заливку при использовании команды "Заменить векторы " - + Use higher DPI for calculations - Slower but more accurate Режим высокого разрешения - медленнее, но точнее - + Tools Инструменты - + Small Маленький - + Large Большой - + Crosshair - + Default По умолчанию - + Left-Handed Левша - + Simple Простой - + Xsheet Xsheet - + Xsheet Autopan during Playback Автозапуск Xsheet во время воспроизведения - + Ignore Alpha Channel on Levels in Column 1 Игнорировать альфа-канал на уровнях в столбце 1 - + Show Keyframes on Cell Area Показывать ключи в областях ячеек - + Use Arrow Key to Shift Cell Selection Использовать клавиши-стрелки для добавления ячеек к выбору - + Enable to Input Cells without Double Clicking Редактировать ввод ячеек одним кликом - + Enable OpenToonz Commands' Shortcut Keys While Renaming Cell Включить шоткаты команд OpenToonz при переименовании ячеек - + Show Toolbar in the XSheet Показывать панель инструментов в Xsheet - + Show Column Numbers in Column Headers Отображать номера столбцов в их заголовках - + Sync Level Strip Drawing Number Changes with the Xsheet Синхронно менять номер наброска в Level Strip с Xsheet - + Classic Классический - + Classic-revised Классический-пересмотренный - + Compact Компактный - + Show Current Time Indicator (Timeline Mode only) Показывать индикатор текущего времени (только на таймлайне) - + Animation Анимация - + Preview Предпросмотр - + Rewind after Playback Возврат к началу после воспроизведения - + Display in a New Flipbook Window Отображение в новом окне Flipbook - + Fit to Flipbook По размеру Flipbook - + Onion Skin Калька - + Onion Skin ON Вкл кальку - + Show Onion Skin During Playback Показывать кальку во время воспроизведения - + + Use Onion Skin Colors for Reference Drawings of Shift and Trace + + + + Display Lines Only Отображать только линии - + Check for the Latest Version of OpenToonz on Launch Проверять наличие последней версии OpenToonz при запуске - + + Tablet Settings + + + + + Enable Windows Ink Support* (EXPERIMENTAL) + + + + Choosing this option will set initial location of all file browsers to $scenefolder. Also the initial output destination for new scenes will be set to $scenefolder as well. Выберите этот параметр, чтобы задать начальный путь для всех обозревателей файлов для $scenefolder. Кроме того, папка назначения визуализации на момент создания новой сцены также имеет значение $scenefolder. - + Graph Editor Opens in Popup Редактор графиков открывается во всплывающем окне - + Spreadsheet Opens in Popup Электронная таблица откроется во всплывающем окне - + Toggle Between Graph Editor and Spreadsheet Переключение между редактором графиков и электронной таблицей - + + Constant + + + + + Exponential + + + + + Expression + + + + + File + Файл + + + Function Editor*: Редактор функций*: - Weight *: - Начертание *: + Начертание *: - + 3DLUT File for [%1] *: 3DLUT файл для [%1]*: - + OpenToonz can use FFmpeg for additional file formats. OpenToonz может использовать FFmpeg для дополнительных форматов файлов. - + FFmpeg is not bundled with OpenToonz. FFmpeg не поставляется с OpenToonz. - + Cursor Options Настройки курсора - + Basic Cursor Type: Базовый тип курсора: - + Cursor Style: Стиль курсора: - + Column Header Layout*: Макет заголовка столбца*: - + Transparency Check Проверка прозрачности - + Version Control Управление версиями - + Enable Version Control* Включить систему управления версиями* - + Automatically Refresh Folder Contents Автоматически обновлять содержимое папки - + Project Folder Aliases (+drawings, +scenes, etc.) Псевдонимы папок проекта (+drawings, +scenes, и т.д.) - + Scene Folder Alias ($scenefolder) Псевдоним папки сцены ($scenefolder) - + Use Project Folder Aliases Only Использовать только псевдонимы папок проекта - + This option defines which alias to be used if both are possible on coding file path. Этот параметр используется для замены пути к файлу псевдонимом. Задайте предпочитаемый псевдоним. - + Always ask before loading or importing Всегда спрашивать перед загрузкой или импортом - + Always import the file to the current project Всегда импортировать файл в текущий проект - + Always load the file from the current location Всегда загружать файл из текущего местоположения - + Strokes Штрихи - + Guides Руководства - + All Все - + Open the dropdown to display all options Открыть раскрывающийся список для отображения всех параметров - + Cycle through the available options Циклический выбор параметров - + Cells Only Только ячейки - + Cells and Column Data Ячейки и данные столбцов - + Theme: Тема: - + Font *: Шрифт: - + + Style *: + + + + Default File Import Behavior: Импорт файлов по умолчанию: - + Default TLV Caching Behavior: Кэшировать TLV изображения: - + Column Icon: Значок столбца: - + cm см - + mm мм - + inch дюйм - + field поле - + pixel пиксель - + Mouse Cursor Курсор мыши - + Viewer Center Просмотр центра - - - + + + On Demand По требованию - + All Icons Все иконки - + All Icons & Images Все иконки и изображения - - - + + + At Once Сразу - + Life is too short for Comic Sans - + Good luck. You're on your own from here. - + Colors Цвета @@ -8157,92 +8501,92 @@ if both are possible on coding file path. Интеграция похожих цветов в один стиль - + Toonz Vector Level Векторный уровень Toonz - + Toonz Raster Level Растровый уровень Toonz - + Raster Level Растровый уровень - + Disabled Отключено - + Enabled Включено - + Use Xsheet as Animation Sheet Использовать Xsheet как лист анимации - + Linear Линейный - + Speed In / Speed Out Speed In / Speed Out - + Ease In / Ease Out Ease In / Ease Out - + Ease In / Ease Out % Ease In / Ease Out % - + Arrow Markers Маркеры стрелок - + Animated Guide Анимированные подсказки при рисовании - + Category Категория - + Interval(Minutes): Интервал (в минутах): - + Undo Memory Size (MB) Емкость памяти отмены (МБ) - + Render Task Chunk Size: Размер блока рендерных задач: - + Additional Project Locations Дополнительные местоположения проекта - + Path Alias Priority: Приоритет псевдонимов, используемых для путей к файлам: @@ -8251,74 +8595,85 @@ if both are possible on coding file path. Стиль: - + Pixels Only: Только пиксели: - + Unit: Единица: - + Camera Unit: Камера: - + Rooms*: Rooms*: - + Icon Size * Размер иконки * - + X X - + Viewer Shrink ? Viewer Shrink - + Step Шаг - + + Matte color is used for background when overwriting raster levels with transparent pixels +in non alpha-enabled image format. + + + + + Matte color: + + + + Viewer BG Color Цвет фона просмотра - + Preview BG Color Цвет фона предпросмотра - + ChessBoard Color 1 Цвет клетки 1 - + Chessboard Color 2 Цвет клетки 2 - + Viewer Zoom Center дальше будет понятно из контекста Зуммировать относительно - + Language *: Язык *: @@ -8331,7 +8686,7 @@ if both are possible on coding file path. Иконка столбца - + Level Settings by File Format: Настройки уровня по формату файла: @@ -8356,142 +8711,147 @@ if both are possible on coding file path. СОХРАНИТЕ ВАШУ РАБОТУ перед экспортом в формате MP4, WEBM или GIF. - + Please provide the path where FFmpeg is located on your computer. Укажите путь, где FFmpeg находится на вашем компьютере. - + FFmpeg Path: Путь к FFmpeg: - + Number of seconds to wait for FFmpeg to complete processing the output: Количество секунд ожидания FFmpeg для завершения обработки выходных данных: - + Note: FFmpeg begins working once all images have been processed. Примечание: FFmpeg начинает работать после обработки всех изображений. - + FFmpeg Timeout: FFmpeg перерыв: - + Please indicate where you would like exports from Fast Render(MP4) to go. Укажите, где вы хотите экспортировать Fast Render (MP4) для перехода. - + Fast Render Path: Путь быстрого рендера: - + Scan File Format: Формат файла сканирования: - + Default Level Type: Тип уровня по умолчанию: - + Width: Ширина: - + Height: Высота: - + Autocreation: Автосоздание: - + Vector Snapping: - + Replace Vectors with Simplified Vectors Command Заменить вектора упрощенными векторами - + Dropdown Shortcuts: - + Next/Previous Step Frames: Шаг следующего/предыдущего кадра: - + Cell-dragging Behaviour: Поведение при перетаскивании ячейки: - + + Current Column Color: + + + + Default Interpolation: Интерполяция по умолчанию: - + Animation Step: Шаг анимации: - + Blank Frames: Пустые кадры: - + Blank Frames Color: Цвет пустых кадров: - + Paper Thickness: Толщина бумаги: - + Previous Frames Correction: Коррекция предыдущих кадров: - + Following Frames Correction: Коррекция последующих кадров: - + Vector Guided Style: - + Ink Color on White Bg: Цвет штриха на белом фоне: - + Ink Color on Black Bg: Цвет штриха на черном фоне: - + Paint Color: Цвет краски: @@ -8499,22 +8859,22 @@ if both are possible on coding file path. PreferencesPopup::FormatProperties - + Level Settings by File Format Настройки уровня по формату файла - + Name: Имя: - + Regular Expression: Регулярное выражение: - + Priority Приоритет @@ -8522,12 +8882,12 @@ if both are possible on coding file path. Previewer - + The file name cannot be empty or contain any of the following characters:(new line) \ / : * ? " | Имя файла не может быть пустым или содержать любой из следующих символов: (новая строка) \ /: *? "| - + File %1 already exists. Do you want to overwrite it? Файл «%1» уже существует. @@ -8736,17 +9096,17 @@ Do you want to overwrite it? QApplication - + New Scene Новая сцена - + Load Scene Загрузить сцену - + Quit Выйти @@ -8754,26 +9114,26 @@ Do you want to overwrite it? QObject - + - - - + + + - + Yes Да - - + + - - - + + + - + No Нет @@ -8785,19 +9145,19 @@ Do you want to overwrite it? - - + + - - - - - - + + + + + + - + Overwrite Перезаписать @@ -8813,85 +9173,90 @@ Do you want to overwrite it? - - - + + + - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - + + - - - + + + Cancel Отмена - + + Apply Antialias + Применить сглаживание + + + - - + + The current selection is invalid. Текущий выбор недействителен. - + Are you sure you want to override Вы действительно хотите переопределить - + Override Переопределение - + It is not possible to save the curve. Сохранение кривой невозможно. - + It is not possible to load the curve. Невозможно загрузить кривую. - + It is not possible to export data. Экспорт данных невозможен. @@ -8930,18 +9295,18 @@ Save the scene first. - - + + The resolution of the output camera does not fit with the options chosen for the output file format. Разрешение выходной камеры не соответствует параметрам, выбранным для формата выходного файла. - + FFmpeg not found, please set the location in the Preferences and restart. FFmpeg не найден, укажите местоположение в настройках и перезапустите. - + It is not possible to complete the rendering. Выполнение рендеринга невозможно. @@ -8981,7 +9346,7 @@ Save the scene first. - + Cleanup Settings Настройки очистки @@ -8994,8 +9359,8 @@ Save the scene first. - - + + Don't Overwrite Не перезаписывать @@ -9018,8 +9383,8 @@ Do you want to save your changes? - - + + Save Сохранить @@ -9058,7 +9423,7 @@ Are you sure ? - + Delete Удалить @@ -9068,33 +9433,48 @@ Are you sure ? Вы действительно хотите удалить выбранный цвет очистки? - + Deactivate Onion Skin Деактивировать Onion Skin - + Limit Onion Skin To Level Ограничить Onion Skin для уровня - + Extend Onion Skin To Scene Расширьте Onion Skin сцены - + + Clear All Onion Skin Markers + + + + + Clear All Fixed Onion Skin Markers + + + + + Clear All Relative Onion Skin Markers + + + + Activate Onion Skin Активировать Onion Skin - - + + Saving previewed frames.... Сохранение кадров предпросмотра .... - + %1 has an invalid extension format. %1 имеет недопустимый формат расширения. @@ -9211,43 +9591,43 @@ Are you sure ? Хранить оригинальную палитру - + Insert Frame at Frame %1 Вставить рамку в кадр %1 - + Remove Frame at Frame %1 Удалить рамку в кадре %1 - + Insert Multiple Keys at Frame %1 Вставка нескольких ключей в кадр %1 - + Remove Multiple Keys at Frame %1 Удаление нескольких ключей в кадре %1 - - + + Change current drawing %1 Изменить текущий рисунок %1 - + New Note Level Новый уровень заметок - + Set Keyframe : %1 Установить ключевой кадр: %1 - + The %1 file has been generated Файл %1 был сгенерирован @@ -9311,39 +9691,43 @@ Are you sure ? Поместить только столбцы в основной xsheet. - + Delete Level : %1 Удалить уровень : %1 - + No unused levels Нет неиспользованных уровней - + It is not possible to delete the used level %1. Удалить использованный уровень %1 невозможно. - + No cleaned up drawings available for the current selection. Для текущего выбора нет очищенных рисунков. - + No saved drawings available for the current selection. Нет доступных сохраненных рисунков для текущего выбора. - + Revert To %1 : Level %2 Возврат к %1: Уровень %2 - + + The Reload command is not supported for the current selection. + + + The Revert to Last Saved command is not supported for the current selection. - Команда «Отменить к последнему сохраненному» не поддерживается для текущего выбора. + Команда «Отменить к последнему сохраненному» не поддерживается для текущего выбора. @@ -9400,29 +9784,29 @@ Do you want to import it or load it from its original location? Конвертирование %1 изображений в формат tlv... - + %1: the current scene has been modified. What would you like to do? %1 текущая сцена была изменена. Что вы хотите сделать? - + Save All Сохранить все - + Save Scene Only Сохранить только сцену - + Discard Changes Отменить изменения - + The following file(s) have been modified. @@ -9431,31 +9815,31 @@ What would you like to do? - + What would you like to do? Что вы хотите сделать? - + Save Changes Сохранить изменения - + Anyway В любом случае - - - + + + OK OK - + %1 has an invalid file extension. %1 имеет недопустимое расширение файла. @@ -9465,55 +9849,61 @@ What would you like to do? Всегда выполнять это действие. - + %1 is an invalid path. %1 - недопустимый путь. - + The scene %1 already exists. Do you want to overwrite it? Сцена %1 уже существует. Вы хотите переписать ее? - - - + + Couldn't load %1 + + + + + + + Couldn't save %1 Не удалось сохранить %1 - + The level %1 already exists. Do you want to overwrite it? Уровень %1 уже существует. Вы хотите переписать его? - + Overwrite Palette Переписать палитру - + Don't Overwrite Palette Не перезаписывать палитру - + The soundtrack %1 already exists. Do you want to overwrite it? Саундтрек %1 уже существует. Вы хотите переписать его? - + File %1 doesn't look like a TOONZ Scene Файл %1 не похож на сцену TOONZ - + A prior save of Scene '%1' was critically interupted. A partial save file was generated and changes may be manually salvaged from '%2'. @@ -9525,34 +9915,34 @@ Do you wish to continue loading the last good save or stop and try to salvage th Хотите продолжить загрузку последнего сохраненного файла или приостановить загрузку, чтобы попытаться восстановить его из временного файла сохранения? - + Continue Продолжить - + It is not possible to load the scene %1 because it does not belong to any project. Невозможно загрузить сцену %1, потому что она не принадлежит ни одному проекту. - + The Scene '%1' belongs to project '%2'. What do you want to do? Сцена «%1» относится к проекту «%2». Что вы хотите сделать? - + Import Scene Импорт сцены - + Change Project Сменить проект - + There were problems loading the scene %1. @@ -9561,31 +9951,31 @@ What do you want to do? Некоторые файлы могут отсутствовать. - + There were problems loading the scene %1. Some levels have not been loaded because their version is not supported Возникли проблемы с загрузкой сцены %1. Некоторые уровни не загружены, потому что их версия не поддерживается - + This scene is incompatible with pixels only mode of the current OpenToonz version. What would you like to do? Эта сцена несовместима с режимом "только пиксели" текущей версии OpenToonz. Чтовы хотите делать? - + Turn off pixels only mode Отключить режим "только пиксели" - + Keep pixels only mode on and resize the scene Оставить режим "только пиксели" и изменить размер сцены - + File '%1' will reload level '%2' as a duplicate column in the xsheet. Allow duplicate? @@ -9594,28 +9984,28 @@ Allow duplicate? Разрешить дубликаты? - + Allow Позволить - + Allow All Dups Разрешить все дупликаты - + No to All Dups Не разрешать дублирование - - + + It is not possible to load the level %1 Невозможно загрузить уровень %1 - + The following level(s) use path with $scenefolder alias. @@ -9624,7 +10014,7 @@ Allow duplicate? - + They will not be opened properly when you load the scene next time. What do you want to do? @@ -9633,88 +10023,88 @@ What do you want to do? Что Вы хотите делать? - + Copy the levels to correspondent paths Копировать уровни в соответствующие пути - + Decode all $scenefolder aliases Декодировать все псевдонимы $scenefolder - + Save the scene only Сохранить только сцену - + Overwrite for All Перезаписать для всех - + Don't Overwrite for All Не перезаписывать для всех - - + + Failed to overwrite %1 Не удалось перезаписать %1 - + No Current Level Нет текущего уровня - + No Current Scene Нет текущей сцены - + Save the scene first Сначала сохранить сцену - + Save level Failed Ошибка сохранения уровня - + Are you sure you want to save the Default Settings? Вы действительно хотите сохранить настройки по умолчанию? - + It is not possible to load the %1 level. Невозможно загрузить уровень %1. - + The scene %1 doesn't exist. Сцены %1 не существует. - + Revert: the current scene has been modified. Are you sure you want to revert to previous version? Revert: текущая сцена была изменена. Вы действительно хотите вернуться к предыдущей версии? - + Revert Возвратиться - + The copied selection cannot be pasted in the current drawing. Скопированный выбор не может быть вставлен в текущий рисунок. @@ -9786,114 +10176,114 @@ Are you sure you want to revert to previous version? Промежуточные кадры : Уровень %1 - + It is not possible to paste the columns: there is a circular reference. Вставить столбцы невозможно: имеется круговой референс. - + Paste Column : Всавить столбец : - + Delete Column : Удалить столбец : - + Insert Column : Вставить столбец : - + Resequence : Col%1 Пересчитать секвенцию : Кол%1 - + Clone Sub-xsheet : Col%1 Клонировать Sub-xsheet : Кол%1 - + Clear Cells : Col%1 Очистить ячейки: Кол%1 - + Reverse Обратить - + Swing Добавить в обратном порядке - + Autoexpose Автоэкспонирование - + Invalid selection: each selected column must contain one single level with increasing frame numbering. Недопустимый выбор: каждый выбранный столбец должен содержать один единственный уровень с увеличением нумерации кадров. - + Random Случайно - + Step %1 Шаг %1 - + Each %1 Каждые %1 - + Reframe to %1's Рекадрировать на %1 - + Reframe to %1's with %2 blanks Перекадрировать в %1 с помощью %2 заготовок - + Roll Up Первый вниз - + Roll Down Последний наверх - + Clone Level : %1 > %2 Клонировать уровень : %1 > %2 - + Clone Levels : Клонировать уровни : - + Ok Ок - + FlipBook Flipbook @@ -10022,8 +10412,8 @@ Are you sure? Не удалось найти выбранную сцену. - - + + Script Console Консоль скриптов @@ -10090,7 +10480,7 @@ Are you sure? TWAIN недоступен. - + Run script Запустить скрипт @@ -10100,12 +10490,12 @@ Are you sure? Создать проект - + Image DPI Изображение DPI - + Custom DPI Пользовательский DPI @@ -10116,17 +10506,27 @@ Are you sure? + Error + + + + + No Palette loaded. + + + + Warning Предупреждение - + Palette is locked. Палитра заблокирована. - + Create Level %1 at Column %2 Создать уровень %1 в столбце %2 @@ -10138,7 +10538,7 @@ Are you sure? \ /: *? "<> | - + File %1 already exists. Do you want to overwrite it? @@ -10203,59 +10603,59 @@ What do you want to do? - - + + File Browser Браузер файлов - + Duplicate Дублировать - + Paste Key Frames Вставить ключевые кадры - + Delete Key Frames Удалить ключевые кадры - + Copy File Копировать файл - + Paste File : Вставить файл : - + Duplicate File : Дублировать файл : - + Task added to the Batch Render List. Задача добавлена в список пакетного рендеринга. - + Task added to the Batch Cleanup List. Задача добавлена в список пакетной очистки. - + Deleting %1. Are you sure? Удаление %1. Вы уверены? - + Deleting %n files. Are you sure? Удаление %n файлов. Вы уверены? @@ -10264,193 +10664,219 @@ What do you want to do? - + A convertion task is in progress! wait until it stops or cancel it по идее здесь обязан быть вопросительный знак Выполняется задача конвертации! Подождать, пока она закончится, или отменить? - + You are going to premultiply selected files. The operation cannot be undone: are you sure? Вы собираетесь сделать premultiply выбранных файлов. Операция не может быть отменена: вы уверены? - + Premultiply Premultiply - + There are no assets to collect Нет активов для сбора - + One asset imported Один импортированный актив - + %1 assets imported Импортировано %1 активов - + + A separation task is in progress! wait until it stops or cancel it + + + + Error loading scene %1 :%2 Ошибка загрузки сцены %1 :%2 - + Error loading scene %1 Ошибка загрузки сцены %1 - + There was an error saving the %1 scene. Ошибка с сохранением сцены %1. - + No scene imported Нет импортированной сцены - + One scene imported Одна сцена импортирована - + %1 scenes imported %1 импортированных сцен - + It is not possible to delete the selection. Удалить выделение невозможно. - + Paste Cells Вставить ячейки - + Delete Cells Удалить ячейки - + Cut Cells Вырезать ячейки - + Insert Cells Поместить ячейки - + It is not possible to paste vectors in the current cell. Невозможно вставить векторы в текущую ячейку. - + Paste (Strokes) Вставить (штрихи) - + It is not possible to paste image on the current cell. Невозможно вставить изображение в текущую ячейку. - - + + Paste Вставить - + Paste (Raster) Вставить (Растр) - + Overwrite Paste Cells Заменить вставленные ячейки - + Paste Numbers Вставлять номер видео - - + + Rename Cell at Column %1 Frame %2 Переименовать ячейку в столбце %1 Кадр %2 - + Fill In Empty Cells Заполнить пустые ячейки - - - + + Duplicate Frame in XSheet + + + + + + No data to paste. Нет данных для вставки. - - - + + + It is not possible to paste the cells: there is a circular reference. Невозможно вставить ячейки: имеется круговой референс. - - + + It is not possible to paste data: there is nothing to paste. Невозможно вставить данные: нечего вставлять. - - + + Please enable "Sync Level Strip Drawing Number Changes with the XSheet" preference option +to use the duplicate command in the xsheet / timeline. + + + + + Please select only one layer to duplicate a frame. + + + + + Please select only one frame to duplicate. + + + + + Cannot paste data Nothing to paste Не удается вставить данные Нечего вставлять - + It is not possible to paste the cells: Some column is locked or column type is not match. Вставить в ячейку невозможно. Столбец заблокирован или его формат не поддерживается. - - + + This command only works on vector cells. Эта команда работает только с векторными ячейками. - + Please select only one column for this command. Пожалуйста, выберите только один столбец для этой команды. - + All selected cells must belong to the same level. Все выбранные ячейки должны принадлежать к одному и тому же уровню. - + Simplify Vectors : Level %1 Упрощение векторов : уровень %1 @@ -10465,11 +10891,16 @@ The operation cannot be undone: are you sure? Изображения предварительного просмотра еще не готовы. - + Xsheet Xsheet + + Timeline + + + Modify Play Range : %1 - %2 Изменить диапазон воспроизведения : %1 - %2 @@ -10500,129 +10931,129 @@ The operation cannot be undone: are you sure? Переместить столбцы - + Change Pegbar Изменить Pegbar - + Change Text at Column %1 Frame %2 Изменить текст в столбце %1 кадре %2 - + Toggle cycle of %1 Переключить цикл %1 - + Move Level Переместить уровень - - + + Schematic Схемы - + Stage Schematic - + Fx Schematic - + Palette Палитра - - + + Studio Palette Палитра Studio - - + + Style Editor Редактор стилей - - + + Viewer Просмотрщик - + Command Bar Панель команд - + Tool Options Настройки инструмента - + Tasks Задания - + Batch Servers Пакетные серверы - - + + Scene Cast Состав сцены - - + + Export Экспортировать - - + + Function Editor Редактор функций - - + + Message Center Центр сообщений - + LineTest Viewer LineTest просмотрщик - + LineTest Capture LineTest захват - - + + Combo Viewer ComboViewer - - + + History История @@ -10676,37 +11107,37 @@ The operation cannot be undone: are you sure? Match lines могут быть удалены только из растровых уровней Toonz - + Level: Уровень: - + Skipping frame. Пропуск кадра. - + Don't Duplicate Не дублировать - + The specified name is already assigned to the %1 file. Указанное имя уже присвоено файлу %1. - + Warning: level %1 already exists; overwrite? Предупреждение: уровень %1 уже существует; перезаписать? - + It is not possible to rename the %1 file. Невозможно переименовать файл %1. - + It is not possible to copy the %1 file. Невозможно скопировать файл %1. @@ -10726,7 +11157,7 @@ The operation cannot be undone: are you sure? Продолжить все - + Move Level to Cast Folder Переместить уровень в папку Cast @@ -10769,7 +11200,7 @@ The operation cannot be undone: are you sure? - + It is possible to merge only Toonz vector levels or standard raster levels. разве?? Можно объединить только уровни векторов Toonz или стандартные уровни растра. @@ -10855,53 +11286,58 @@ The operation cannot be undone: are you sure? В указанном диапазоне кадров нет рисунка. - + Cannot open menubar settings template file. Re-installing Toonz will solve this problem. Не удается открыть файл шаблонов настроек меню. Повторная установка Toonz решит эту проблему. - + No more Undo operations available. Больше нет операций Undo. - + No more Redo operations available. Больше нет операций Redo. - + The rooms will be reset the next time you run Toonz. Вкладки будут восстановлены при следующем запуске OpenToonz. - + Visit Web Site Посетить сайт - + An update is available for this software. Visit the Web site for more information. Доступно обновление программного обеспечения. Подробную информацию можно найти на веб-сайте. - + Check for the latest version on launch. Проверять наличие обновлений при запуске. - + https://opentoonz.github.io/e/ https://opentoonz.github.io/e/ - + Installing %1 again could fix the problem. Установка %1 снова может устранить проблему. + + The qualifier %1 is not a valid key name. Skipping. + + + Selected folders don't belong to the current project. Do you want to import them or load from their original location? @@ -10914,7 +11350,7 @@ Do you want to import them or load from their original location? Применить данные липсинк - + Layer name Имя слоя @@ -10970,38 +11406,38 @@ Do you want to import them or load from their original location? RenameAsToonzPopup - + The file name cannot be empty or contain any of the following characters:(new line) \ / : * ? " | Имя файла не может быть пустым или содержать любой из следующих символов: (новая строка) \ /: *? "| - - + + Rename Переименовать - + Renaming File Переименование файла - + Creating an animation level of %1 frames Создание анимационного уровня из %1 кадров - + Delete Original Files Удалить исходные файлы - + Level Name: Имя уровня: - + Cancel Отмена @@ -11462,79 +11898,79 @@ The audio file will not be included in the rendered clip. SVNLockDialog - + Version Control: Edit Управление версиями: Редактировать - + Version Control: Unlock Управление версиями: Разблокировка - + Getting repository status... Получение статуса репозитория... - + Comment: Комментарий: - + Edit Scene Contents Изменить содержание сцены - + Unlock Scene Contents Разблокировать содержание сцены - + Edit Правка - + Unlock Разблокировать - + Cancel Отмена - + No items to edit. Нет объектов для редактирования. - + No items to unlock. Нет элементов для разблокировки. - - + + %1 items to edit. %1 элементов для редактирования. - - + + %1 items to unlock. %1 предметов для разблокировки. - + Editing %1 items... Изменение %1 объектов... - + Unlocking %1 items... Разблокировка %1 предметов... @@ -11596,32 +12032,32 @@ The audio file will not be included in the rendered clip. SVNLockInfoDialog - + Version Control: Edit Info Управление версиями: Редактировать инфо - + <b>Edited By:</b> <b> Отредактировано:</b> - + <b>Host:</b> <b>Host:</b> - + <b>Comment:</b> <b>Комментарий:</b> - + <b>Date:</b> <b>Дата:</b> - + Close Закрыть @@ -12162,14 +12598,22 @@ Please commit or revert changes first. + SaveBoardPresetFilePopup + + + Save Clapperboard Settings As Preset + + + + SaveCurvePopup - + Save Curve Сохранить кривую - + Save Сохранить @@ -12177,12 +12621,12 @@ Please commit or revert changes first. SaveImagesPopup - + Save Flipbook Images Сохранить изображения Flipbook - + Save Сохранить @@ -12259,12 +12703,12 @@ Please commit or revert changes first. SavePreviewedPopup - + Save Previewed Images Сохранить просмотренные изображения - + Save Сохранить @@ -12530,218 +12974,424 @@ Please commit or revert changes first. SceneViewerPanel - + Safe Area (Right Click to Select) Безопасная зона (Щелкните правой кнопкой мыши, чтобы выбрать) - + Field Guide Направляющая сетка - + Camera Stand View Стандартный вид с камеры - + 3D View 3D-просмотр - + Camera View Вид с камеры - + Freeze Заморозить - + Preview Предпросмотр - + Sub-camera Preview Предпросмотр суб-камеры - + Untitled Безымянный - + Scene: Сцена: - + :: Frame: :: Кадр: - - + + :: Zoom : :: Зум : - - + + (Flipped) - + :: Level: :: Уровень: - + Level: Уровень: + SeparateColorsPopup + + + Auto + Авто + + + + Preview + Предпросмотр + + + + Separate + + + + + Close + Закрыть + + + + Sub Color 3: + + + + + Alpha Matting + + + + + Main + + + + + Sub1 + + + + + Sub2 + + + + + Sub3 + + + + + Pick Color + + + + + Show Mask + + + + + Show Alpha + + + + + Preview Frame: + + + + + Paper Color: + + + + + Main Color: + + + + + Sub Color 1: + + + + + Sub Color 2: + + + + + Sub Adjust: + + + + + Border Smooth: + + + + + Mask Threshold: + + + + + Mask Radius: + + + + + Start: + + + + + End: + Конец: + + + + Format: + Формат: + + + + Save in: + Сохранить в: + + + + File Suffix: + + + + + Cancel + Отмена + + + + Separate by colors ... + + + + + Separate 1 Level + + + + + Separate %1 Levels + + + + + Critical + + + + + Failed to access the destination folder! + + + + + Separating %1 + + + + + Converting level %1 of %2: %3 + Конвертация уровня %1 из %2: %3 + + + + SeparateSwatch + + + Sub Color 3 + + + + + Original + + + + + Main Color + + + + + Sub Color 1 + + + + + Sub Color 2 + + + + ShortcutPopup - + Configure Shortcuts Настроить хоткеи - + Remove Удалить + - Export Current Shortcuts Экспорт текущих хоткеев - + Delete Удалить - + Delete Current Preset Удалить текущий пресет - + Save As Сохранить как - + Save Current Shortcuts as New Preset Сохранить текущие хоткеи в новом пресете - + Load Загрузить - + Use selected preset as shortcuts Использовать выбранные пресеты как хоткеи - + Shortcut Presets Пресеты хоткеев - + Clear All Shortcuts Удалить все хоткеи - + Couldn't find any matching command. Не удалось найти подходящую команду. - + Search: Поиск: - + Preset: Предустановка: - + This will erase ALL shortcuts. Continue? Это приведет к удалению всех хоткеев. Продолжить? - + This will overwrite all current shortcuts. Continue? Это перезапишет все текущие ярлыки. Продолжить? - + A file named Файл с именем - + already exists. Do you want to replace it? уже существует. Хотите заменить его? - + OpenToonz - Setting Shortcuts OpenToonz - Настройка хоткеев - + Saving Shortcuts Сохранить хоткеи - + Included presets cannot be deleted. Включенные пресеты не могут быть удалены. - + Are you sure you want to delete the preset: Вы действительно хотите удалить пресет: - + ? ? - + Setting Shortcuts Настройки сочетаний клавиш - + Load from file... Загрузить из файла... - + Enter Preset Name Введите имя пресета - + Preset Name: Имя пресета: @@ -12749,112 +13399,112 @@ Please commit or revert changes first. ShortcutTree - + Menu Commands Команды меню - + Fill Заливка - + File Файл - + Edit Редактировать - + Scan & Cleanup Сканирование и очистка - + Level Уровень - + Xsheet Xsheet - + Cells Ячейки - + View Вид - + Windows Окна - + Right-click Menu Commands Меню команд правого клика - + Tools Инструменты - + Tool Modifiers Модификаторы инструментов - + Visualization Визуализация - + Misc Прочее - + Playback Controls Управление воспроизведением - + RGBA Channels Каналы RGBA @@ -12869,19 +13519,19 @@ Please commit or revert changes first. ShortcutViewer - + %1 is already assigned to '%2' Assign to '%3'? %1 уже присвоен '%2' Присвоить значение '%3'? - + Yes Да - + No Нет @@ -12901,16 +13551,16 @@ Assign to '%3'? - - - - + + + + Files Файлы - + Scan Сканирование @@ -12926,149 +13576,149 @@ Assign to '%3'? - - - - + + + + Edit Правка - - - - - + + + + + Windows Окна - - - - + + + + Other Windows Другие окна - - - - - - + + + + + + Customize Настроить - - - - - + + + + + View Вид - - - - - - - + + + + + + + Help Справка - - + + Tools Инструменты - - + + More Tools Другие инструменты - - + + Checks Проверки - - + + Render Рендер - + Draw Рисовать - - + + Xsheet Xsheet - + Subxsheet Subxsheet - + Levels Уровни - - + + Cells Ячейки - + Reframe Перестроить - + Step Шаг - + Each Каждый - + File Файл - + Scan && Cleanup Сканирование и очистка - + Level Уровень - + Cannot open menubar settings file %1 Не удается открыть файл настроек меню %1 - + Failed to create menubar Не удалось создать меню @@ -13720,7 +14370,7 @@ Possibly the preset file has been corrupted TopBar - + Lock Rooms Tab Заблокировать вкладки @@ -13978,22 +14628,22 @@ Possibly the preset file has been corrupted VersionControl - + The version control configuration file is empty or wrongly defined. Please refer to the user guide for details. Файл конфигурации управления версиями пуст или неправильно определен. Подробнее см. В руководстве пользователя. - + The version control client application specified on the configuration file cannot be found. Please refer to the user guide for details. Клиентское приложение управления версиями, указанное в файле конфигурации, не может быть найдено. Подробнее см. В руководстве пользователя. - - + + The version control client application is not installed on your computer. Subversion 1.5 or later is required. Please refer to the user guide for details. @@ -14002,7 +14652,7 @@ Please refer to the user guide for details. Подробнее см. В руководстве пользователя. - + The version control client application installed on your computer needs to be updated, otherwise some features may not be available. Subversion 1.5 or later is required. Please refer to the user guide for details. @@ -14022,77 +14672,77 @@ Please refer to the user guide for details. XsheetGUI::CellArea - + Click to select keyframe, drag to move it Кликнуть для выделения кадра, потянуть для перемещения - + Click and drag to set the acceleration range Нажмите и перетащите, чтобы установить диапазон ускорения - + Click and drag to set the deceleration range Нажмите и перетащите, чтобы установить диапазон замедления - + Set the cycle of previous keyframes Установите цикл предыдущих ключевых кадров - + Click and drag to move the selection Кликнуть и потянуть для перемещения выделенного - + Click and drag to play Кликнуть и потянуть для воспроизведения - + Click and drag to repeat selected cells Нажмите и перетащите, чтобы повторить выбранные ячейки - + Reframe Перестроить - + Step Шаг - + Each Каждый - + Edit Cell Numbers Ввести номер кадра - + Replace Level Заменить уровень - + Replace with Заменить - + Paste Special Специальная вставка - + Edit Image Редактирование изображений @@ -14101,12 +14751,12 @@ Please refer to the user guide for details. Заменить - + Open Memo Открыть Мемо - + Delete Memo Удалить Мемо @@ -14114,135 +14764,135 @@ Please refer to the user guide for details. XsheetGUI::ColumnArea - + &Subsampling 1 &Субсемплинг 1 - + &Subsampling 2 &Субсемплинг 2 - + &Subsampling 3 &Субсемплинг 3 - + &Subsampling 4 &Субсемплинг 4 - + Click to select camera Нажмите, чтобы выбрать камеру - - + + Click to select column, drag to move it Нажмите, чтобы выбрать столбец, перетащите, чтобы переместить его - + Click to select column Щелкните для выбора столбца - + Click to select column, drag to move it, double-click to edit Нажмите, чтобы выбрать столбец, перетащите, чтобы переместить его, двойной клик чтобы редактировать - + Click to select column, double-click to edit Щелкните для выбора столбца, двойной клик для редактирования - + Lock Toggle Блокировка переключения - + Additional column settings Дополнительные настройки столбцов - + Preview Visibility Toggle Переключение видимости - + Camera Stand Visibility Toggle Переключатель видимости камеры - + &Insert Before &Вставить слева - + &Insert After &Вставить cправа - + &Paste Insert Before - + &Paste Insert After - + &Insert Below &Вставить ниже - + &Insert Above &Вставка сверху - + &Paste Insert Below - + &Paste Insert Above - - + + Click to play the soundtrack back Нажмите, чтобы воспроизвести зв. дорожку - - + + Set the volume of the soundtrack Установите громкость зв. дорожки - + Alt + Click to Toggle Thumbnail Alt + Click для переключения иконок - + Reframe Перестроить - + Subsampling Субдискретизация @@ -14283,30 +14933,55 @@ Please refer to the user guide for details. Фильтр не влияет на уровни вектора - + Filter: Фильтр: + + + Opacity: + + XsheetGUI::NoteArea - + + Toggle Xsheet/Timeline + + + + + Add New Memo + + + + + Previous Memo + + + + + Next Memo + + + + Frame Кадр - + Sec Frame Сек Кадр - + 6sec Sheet 6сек Лист - + 3sec Sheet 3сек Лист @@ -14332,22 +15007,22 @@ Please refer to the user guide for details. XsheetGUI::RowArea - + Playback Start Marker Маркер начала воспроизведения - + Playback End Marker Маркер окончания воспроизведения - + Pinned Center : Col%1%2 Фиксированный центр : Кол%1%2 - + Double Click to Toggle Onion Skin Двойной клик для переключения Onion Skin @@ -14356,47 +15031,78 @@ Please refer to the user guide for details. Текущий кадр - + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + + Click to Move Shift & Trace Marker + + + + Current Frame Текущий кадр - + Fixed Onion Skin Toggle Переключение закрепленной кальки - + Relative Onion Skin Toggle Переключатель кальки относительно кадра - + Set Start Marker Установить стартовый маркер - + Set Stop Marker Установить конечный маркер - + Set Auto Markers Установить авто-маркеры - + Remove Markers Удалить маркеры - + Preview This Просмотреть это + XsheetGUI::SoundColumnPopup + + + Volume: + + + + XsheetGUI::XSheetToolbar diff --git a/toonz/sources/translations/russian/toonzlib.ts b/toonz/sources/translations/russian/toonzlib.ts index 72eec47..2389ff0 100644 --- a/toonz/sources/translations/russian/toonzlib.ts +++ b/toonz/sources/translations/russian/toonzlib.ts @@ -4,17 +4,17 @@ Preferences - + Retas Level Format Формат уровней Retas - + Adobe Photoshop Adobe Photoshop - + PNG PNG @@ -154,62 +154,62 @@ Изменить папку палитры Studio : %1 : %2 > %3 - + Arrange Styles in Palette %1 Упорядочить стили в палитре %1 - + Create Style#%1 in Palette %2 Создать стиль#%1 в палитре %2 - + Add Style to Palette %1 Добавить стиль в палитру %1 - + Add Page %1 to Palette %2 Добавить страницу %1 в палитру %2 - + Delete Page %1 from Palette %2 Удалить страницу %1 из палитры %2 - + Load Color Model %1 to Palette %2 Загрузить цветовую %1 модель в палитру %2 - + color model Цветовая модель - + Move Page Переместить страницу - + Rename Page %1 > %2 Переименовать страницу %1 > %2 - + Rename Style#%1 in Palette%2 : %3 > %4 Переименование стиля#%1 в палитре%2 : %3>%4 - + Set Picked Position of Style#%1 in Palette%2 : %3,%4 Установить выбранное расположение стиля#%1 в палитре%2 :%3,%4 - + Update Colors by Using Picked Positions in Palette %1 Обновление цветов с использованием выбранных расположений в палитре %1 @@ -230,82 +230,82 @@ Создать связанный Fx : %1 - + Replace Fx : Заменить Fx : - + Unlink Fx : %1 - - %2 Разъединить Fx : %1 - - %2 - + Make Macro Fx : %1 Сделать Makro Fx : %1 - + Explode Macro Fx : %1 Разбить Macro Fx : %1 - + Create Output Fx Создать выход Fx - + Connect to Xsheet : Подключить к Xsheet : - + Disconnect from Xsheet : Отключить от Xsheet : - + Delete Link Удалить связь - + Delete Fx Node : %1 Удалить Fx-узел : %1 - + Paste Fx : Вставить Fx : - + Disconnect Fx Отключить Fx - + Connect Fx : %1 - %2 Подключить Fx : %1 - %2 - + Rename Fx : %1 > %2 Переименовать Fx : %1 - %2 - + Group Fx Сгруппировать Fx - + Ungroup Fx Разгруппировать Fx - + Rename Group : %1 > %2 Переименовать группу : %1 > %2 @@ -412,7 +412,7 @@ Векторизация не выполнена - + Argument '%1' does not look like a FrameId Аргумент %1 не похож на FrameId @@ -427,22 +427,22 @@ Аргумент не похож на путь к файлу :%1 - + %1-%2 %1-%2 - + %1 %1 - + Expected %1 argument(s) in %2, got %3 Ожидаемый %1 аргумент(ы) в %2,%3 - + %1 is not a valid color (valid color names are 'red', 'transparent', '#FF8800', ecc.) %1 не является допустимым цветом (допустимые названия цветов: "красный","прозрачный,"#FF8800" и др.) @@ -538,12 +538,12 @@ Порог яркости - + Xsheet - + Timeline Таймлайн @@ -654,77 +654,77 @@ TScriptBinding::Level - + %1 frames %1 кадров - + Bad argument (%1). It should be FilePath or string Плохой аргумент (%1). Это должен быть FilePath или строка - + Exception loading level (%1) Уровень загрузки исключений (%1) - + File %1 doesn't exist Файл %1 не существует - + File %1 is unsupported Файл %1 не поддерживается - + Exception reading %1 Чтение исключений %1 - + Can't save an empty level Не удалось сохранить пустой уровень - + Unrecognized file type : Нераспознанный тип файла : - + Can't save a %1 level to this file type : %2 Не удается сохранить уровень %1 для этого типа файла : %2 - + Exception writing %1 Запись исключений %1 - + frame index (%1) must be a number Индекс кадра (%1) должен быть числом - + frame index (%1) is out of range (0-%2) Индекс кадра (%1) вне диапазона (0-%2) - + second argument (%1) is not an image Второй аргумент (%1) не является изображением - + can not insert a %1 image into a level Невозможно вставить изображение %1 в уровень - + can not insert a %1 image to a %2 level Невозможно вставить изображение %1 в уровень %2 diff --git a/toonz/sources/translations/russian/toonzqt.ts b/toonz/sources/translations/russian/toonzqt.ts index 634f073..526b11f 100644 --- a/toonz/sources/translations/russian/toonzqt.ts +++ b/toonz/sources/translations/russian/toonzqt.ts @@ -91,12 +91,12 @@ CameraPainter - + &Reset Center &Сброс центра - + &Activate &Активировать @@ -104,82 +104,82 @@ CameraSettingsWidget - + DPI DPI - - - + + + Pixels Пиксели - + x x - + Use Current Level Settings Использовать настройки текущего уровня - + Add Добавить - + Remove Удалить - + Force Squared Pixel Force Squared Pixel - + A/R - - + + <custom> <пользовательский> - + Bad camera preset Плохой пресет камеры - + '%1' doesn't seem a well formed camera preset. Possibly the preset file has been corrupted "%1" не кажется правильно сформированным пресетом камеры. Возможно пресет поврежден - + Preset name Имя пресета - + Enter the name for %1 Введите имя для %1 - + Error : Preset Name is Invalid Ошибка: имя пресета недействительно - + The preset name must not use ','(comma). Имя пресета не должно содержать "," (запятую). @@ -228,14 +228,13 @@ Possibly the preset file has been corrupted ColumnPainter - + &Reset Center &Сброс центра - &Open Subxsheet - &Открыть Subxsheet + &Открыть Subxsheet @@ -285,32 +284,32 @@ Possibly the preset file has been corrupted DVGui::CleanupColorField - + Brightness: Яркость: - + Contrast: Контраст: - + Color Thres Цветовой порог - + White Thres Порог белого - + H Range H Range - + Line Width Ширина линии @@ -318,22 +317,22 @@ Possibly the preset file has been corrupted DVGui::ColorField - + R: R: - + G: G: - + B: B: - + A: A: @@ -374,7 +373,7 @@ Possibly the preset file has been corrupted DVGui::FileField - + ... ... @@ -411,7 +410,7 @@ Possibly the preset file has been corrupted DVGui::StyleIndexLineEdit - + current текущий @@ -471,17 +470,17 @@ Possibly the preset file has been corrupted FileSegmentPage - + File Path: Путь к файлу: - + Column: Столбец: - + Unit: Ед. изм: @@ -716,6 +715,19 @@ Possibly the preset file has been corrupted + FontParamField + + + Style: + + + + + Size: + + + + FrameNavigator @@ -755,127 +767,127 @@ Possibly the preset file has been corrupted Кривые функции - + Link Handles Связать Handles - + Unlink Handles Разъединить Handles - + Reset Handles Сбросить Handles - + Delete Удалить - + Set Key Установить ключ - + Activate Cycle Активировать цикл - + Deactivate Cycle Деактивировать цикл - + Linear Interpolation Линейная интерполяция - + Speed In / Speed Out Interpolation Интерполяция Speed In / Speed Out - + Ease In / Ease Out Interpolation Ease In / Ease Out Интерполяция - + Ease In / Ease Out (%) Interpolation Ease In / Ease Out (%) Интерполяция - + Exponential Interpolation Экспоненциальная интерполяция - + Expression Interpolation Интерполяция выражений - + File Interpolation Интерполяция файлов - + Constant Interpolation Равномерная интерполяция - + Similar Shape Interpolation Интерполяция аналогичной формы - + Fit Selection Подогнать выделенное - + Fit Подогнать - + Step 1 Шаг 1 - + Step 2 Шаг 2 - + Step 3 Шаг 3 - + Step 4 Шаг 4 - + Smooth Плавно - + Frame Based Frame Based - + Curve Shape Форма кривой @@ -883,126 +895,126 @@ Possibly the preset file has been corrupted FunctionSegmentViewer - - + + Linear Линейная - + Speed In / Speed Out Speed In / Speed Out - + Ease In / Ease Out Ease In / Ease Out - + Ease In / Ease Out % Ease In / Ease Out % - + Exponential Экспоненциальная - + Expression Выражение - - + + File Файл - + Constant Постоянная - + Similar Shape Аналогичная форма - + Interpolation: Интерполяция: - + Apply Применить - + From От - + To До - + Step Шаг - - + + < < - - + + > > - + Speed Speed - + Ease Ease - + Ease% Ease% - + Expo Expo - + Expr Expr - + Const Const - + Similar Аналогичная - + ???? ???? @@ -1169,55 +1181,54 @@ Possibly the preset file has been corrupted FxColumnPainter - + &Disconnect from Xsheet &Отсоединить от Xsheet - + &Connect to Xsheet &Присоединить к Xsheet - + &Paste Add &Вставить Добавить - + &Preview &Предпросмотр - + &Uncache Fx &Очистить кэш Fx - + &Cache FX &Кэшировать FX - &Open Subxsheet - &Открыть Subxsheet + &Открыть Subxsheet FxOutputPainter - + Output Вывод - + &Delete &Удалить - + &Activate &Активировать @@ -1225,77 +1236,77 @@ Possibly the preset file has been corrupted FxPainter - + &Open Group &Открыть группу - + &Paste Replace &Вставить Заменить - + &Paste Add &Вставить Добавить - + &Delete &Удалить - + &Disconnect from Xsheet &Отсоединить от Xsheet - + &Connect to Xsheet &Присоединить к Xsheet - + &Create Linked FX &Создать связанный FX - + &Unlink &Разъединить - + &Make Macro FX &Сделать Macro FX - + &Explode Macro FX &Разбить Makro FX - + &Open Macro FX &Открыть Makro FX - + &Save As Preset... &Сохранить как пресет... - + &Preview &Предпросмотр - + &Uncache FX &Очистить кэш Fx - + &Cache FX &Кэшировать FX @@ -1303,17 +1314,17 @@ Possibly the preset file has been corrupted FxPalettePainter - + &Disconnect from Xsheet &Отсоединить от Xsheet - + &Connect to Xsheet &Присоединить к Xsheet - + &Preview &Предпросмотр @@ -1321,25 +1332,33 @@ Possibly the preset file has been corrupted FxSchematicLink - + &Delete &Удалить - + &Paste Insert &Вставить вставку + FxSchematicOutputNode + + + Output + Вывод + + + FxSchematicPort - + &Disconnect from Xsheet &Отсоединить от Xsheet - + &Connect to Xsheet &Присоединить к Xsheet @@ -1347,21 +1366,21 @@ Possibly the preset file has been corrupted FxSchematicScene - + Cannot Paste Insert a selection of unconnected FX nodes. Select FX nodes and related links before copying or cutting the selection you want to paste. Невозможно вставить выбранные неподключенные узлы FX. Выберите FX-узлы и связи перед копированием или сокращением выбора, который вы хотите вставить. - + Cannot Paste Add a selection of unconnected FX nodes. Select FX nodes and related links before copying or cutting the selection you want to paste. Невозможно вставить (добавить) выбранные неподключенные узлы FX. Выберите FX-узлы и связи перед копированием или сокращением выбора, который вы хотите вставить. - + Cannot Paste Replace a selection of unconnected FX nodes. Select FX nodes and related links before copying or cutting the selection you want to paste. Невозможно вставить (заменить) выбранные неподключенные узлы FX. @@ -1369,6 +1388,14 @@ Select FX nodes and related links before copying or cutting the selection you wa + FxSchematicXSheetNode + + + XSheet + + + + FxSettings @@ -1409,17 +1436,17 @@ Select FX nodes and related links before copying or cutting the selection you wa FxXSheetPainter - + XSheet - + &Paste Add &Вставить Добавить - + &Preview &Предпросмотр @@ -1427,7 +1454,7 @@ Select FX nodes and related links before copying or cutting the selection you wa GroupPainter - + &Open Group &Открыть группу @@ -1667,22 +1694,22 @@ Select FX nodes and related links before copying or cutting the selection you wa PaletteViewerGUI::PageViewer - + - No Styles - - Нет стилей - - + Name Editor Редактор имен - + New Style Новый стиль - + New Page Новая страница @@ -1730,7 +1757,7 @@ Select FX nodes and related links before copying or cutting the selection you wa PegbarPainter - + &Reset Center &Сброс центра @@ -1738,12 +1765,12 @@ Select FX nodes and related links before copying or cutting the selection you wa PointParamField - + X: X: - + Y: Y: @@ -1755,20 +1782,20 @@ Select FX nodes and related links before copying or cutting the selection you wa <пользовательский> - + Deleting "%1". Are you sure? Удаление «%1». Вы уверены? - - + + Delete Удалить - + @@ -1870,7 +1897,7 @@ Are you sure? Взять цвет из палитры Studio - + Paste Object Встаить объект @@ -1895,38 +1922,38 @@ Are you sure? Переместить ключевой кадр - + Save Motion Path Сохранить траекторию движения - - + + Motion Path files (*.mpath) Файлы траектории движения (* .mpath) - + It is not possible to save the motion path. Невозможно сохранить траекторию движения. - + Load Motion Path Загрузить траекторию движения - + It is not possible to load the motion path. Невозможно загрузить траекторию движения. - + Stage Schematic Stage Schematic - + FX Schematic FX Schematic @@ -1963,67 +1990,68 @@ Are you sure? Заменить - + + Modify Fx Param : %1 Изменить Fx Параметр : %1 - - - + + + Modify Fx Param : %1 : %2 -> %3 Изменить Fx Параметры : %1 : %2 -> %3 - - + + Modify Fx Param : Изменить Fx Параметр : - + ON : %1 ON : %1 - + OFF : %1 OFF : %1 - + Modify Fx Param : %1 : %2 Key Изменить Fx Параметр : %1 : %2 Ключ - - + + Add Добавить - - + + Remove Удалить - + Modify Fx Param : %1 : %2 Point Изменить Fx Параметр : %1 : %2 Точка - + %1 : Linear ON %1 : линейный вкл - + %1 : Linear OFF %1 : линейный откл - + Palette Палитра @@ -2252,6 +2280,8 @@ Are you sure? + + The source image seems not suitable for this kind of conversion Исходное изображение кажется непригодным для такой конверсии @@ -2329,12 +2359,12 @@ Are you sure? Вы уверены? - + Modify Fx Param : %1 Key : %2 Frame %3 Изменить Fx Параметр : %1 Ключ : %2 Кадр %3 - + Set Установить @@ -2420,59 +2450,64 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< SchematicViewer - + &Fit to Window &По размеру окна - + &Focus on Current &Фокус на текущем - + &Reorder Nodes &Изменение порядка узлов - + &Reset Size &Сбросить размер - - - + + + &Minimize Nodes &Минимизировать узлы - - - + + + &Maximize Nodes &Максимизировать узлы - + &New Pegbar &Новый Pegbar - + &New Camera &Новая камера - + &New Motion Path &Новая траектория движения - + &Swtich output port display mode &Переключение отображения выходного порта + + + &Toggle node icons + + SchematicWindowEditor @@ -2485,22 +2520,22 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< SimilarShapeSegmentPage - + Reference Curve: Референсная кривая: - + Frame Offset: Смещение кадра: - + There is a syntax error in the definition of the interpolation. В определении интерполяции имеется синтаксическая ошибка. - + There is a circular reference in the definition of the interpolation. В определении интерполяции имеется круговой референс. @@ -2551,17 +2586,17 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< SplinePainter - + &Delete &Удалить - + &Save Motion Path... &Сохранить траекторию движения... - + &Load Motion Path... &Загрузить траекторию движения... @@ -2569,17 +2604,17 @@ The second line should be "Mesh [Input bit depth] [Output bit depth]"< StageSchematicScene - + &New Pegbar &Новый Pegbar - + &New Motion Path &Новая траектория движения - + &New Camera &Новая камера @@ -2976,12 +3011,12 @@ Apply TablePainter - + Table - + &Reset Center &Сброс центра diff --git a/toonz/sources/translations/spanish/image.ts b/toonz/sources/translations/spanish/image.ts index e3ab794..2a1cd57 100644 --- a/toonz/sources/translations/spanish/image.ts +++ b/toonz/sources/translations/spanish/image.ts @@ -4,12 +4,12 @@ AviWriterProperties - + Codec Compresor - + Uncompressed Sin compresión @@ -70,52 +70,52 @@ intentar aumentar el tiempo de espera en las Preferencias. SgiWriterProperties - + Bits Per Pixel Bits por píxel - + 24 bits 24 bits - + 32 bits 32 bits - + 48 bits 48 bits - + 64 bits 64 bits - + 8 bits (Greyscale) 8 bits (escala de grises) - + Endianess Orden - + Big Endian Mayor al inicio (big endian) - + Little Endian Menor al inicio (little endian) - + RLE-Compressed Compresión RLE @@ -181,37 +181,37 @@ intentar aumentar el tiempo de espera en las Preferencias. SvgWriterProperties - + Stroke Mode Modo de vectorización - + Outline Quality Calidad de contornos - + Centerline Líneas - + Outline Contornos - + High Alta - + Medium Media - + Low Baja @@ -340,12 +340,12 @@ intentar aumentar el tiempo de espera en las Preferencias. WebmWriterProperties - + Quality Calidad - + Scale Escala diff --git a/toonz/sources/translations/spanish/tnztools.ts b/toonz/sources/translations/spanish/tnztools.ts index 2a12f15..f12022b 100644 --- a/toonz/sources/translations/spanish/tnztools.ts +++ b/toonz/sources/translations/spanish/tnztools.ts @@ -96,7 +96,7 @@ Hardness: - Dureza: + Dureza: Accuracy: @@ -144,7 +144,7 @@ Pencil - Lápiz + Lápiz Pressure @@ -224,19 +224,19 @@ Draw Order: - Orden: + Orden: Over All - Por encima + Por encima Under All - Por debajo + Por debajo Palette Order - Según paleta + Según paleta @@ -1341,6 +1341,33 @@ Do you want to proceed? Link Vinculado + + Scale + Escala + + + Position + Posición + + + + ShiftTraceToolOptionBox + + Reset Previous + + + + Reset Following + + + + Previous Drawing + + + + Following Drawing + + SkeletonTool @@ -1422,6 +1449,53 @@ movido hacia el final de la primera página de la paleta. + ToonzRasterBrushTool + + Size + Tamaño + + + Hardness: + Dureza: + + + Smooth: + Estabilidad: + + + Draw Order: + Orden: + + + Over All + Por encima + + + Under All + Por debajo + + + Palette Order + Según paleta + + + Preset: + Ajustes: + + + <custom> + <personalizado> + + + Pencil + Lápiz + + + Pressure + Presión + + + TrackerTool Width: diff --git a/toonz/sources/translations/spanish/toonz.ts b/toonz/sources/translations/spanish/toonz.ts index fbacf49..133780d 100644 --- a/toonz/sources/translations/spanish/toonz.ts +++ b/toonz/sources/translations/spanish/toonz.ts @@ -367,6 +367,92 @@ Detenerla o esperar a su finalización antes de eliminarla. + BoardSettingsPopup + + Clapperboard Settings + + + + Load Preset + + + + Save as Preset + + + + Close + Cerrar + + + Duration (frames): + + + + Text + + + + Project name + + + + Scene name + + + + Duration : Frame + + + + Duration : Sec + Frame + + + + Duration : HH:MM:SS:FF + + + + Current date + + + + Current date and time + + + + User name + + + + Scene location : Aliased path + + + + Scene location : Full path + + + + Output location : Aliased path + + + + Output location : Full path + + + + Image + + + + + BoardView + + Please set the duration more than 0 frame first, or the clapperboard settings will not be saved in the scene at all! + + + + BrightnessAndContrastPopup Brightness and Contrast @@ -2233,6 +2319,25 @@ contuviera información de PPP, entonces se usarán los de la cámara actual. Drag to Extend Onion Skin, Double Click to Toggle All Arrastrar para extender la piel de cebolla, doble clic para alternar todos + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + Click to Move Shift & Trace Marker + + FilmstripFrames @@ -2499,6 +2604,76 @@ Do you want to overwrite it? + ItemInfoView + + Bold + + + + Italic + + + + Ignore + + + + Keep + + + + Name: + Nombre: + + + Type: + Tipo: + + + Path: + Ruta: + + + Aspect Ratio: + + + + Font: + + + + Max Size: + + + + No item selected. + + + + Item + + + + + ItemListView + + Add + Agregar + + + Remove + Eliminar + + + Move Up + + + + Move Down + + + + LayerFooterPanel Zoom in/out of timeline @@ -2997,6 +3172,13 @@ Usar los números de fotograma como referencia. + LoadBoardPresetFilePopup + + Load Clapperboard Settings Preset + + + + LoadColorModelPopup Load Color Model @@ -5116,7 +5298,7 @@ Usar los números de fotograma como referencia. Flip Viewer Horiontally - Invertir visor horizontalmente + Invertir visor horizontalmente Flip Viewer Vertically @@ -5170,6 +5352,50 @@ Usar los números de fotograma como referencia. Active Axis - All Animar - Operación - Todos + + &Timeline + + + + Linear Interpolation + + + + Speed In / Speed Out Interpolation + + + + Ease In / Ease Out Interpolation + + + + Ease In / Ease Out (%) Interpolation + + + + Exponential Interpolation + + + + Expression Interpolation + + + + File Interpolation + + + + Constant Interpolation + + + + Separate Colors... + + + + Flip Viewer Horizontally + + MatchlinesDialog @@ -5748,6 +5974,25 @@ What do you want to do? Render Procesar + + Add Clapperboard + + + + Edit Clapperboard... + + + + Save current output settings. +The parameters to be saved are: +- Camera settings +- Project folder to be saved in +- File format +- File options +- Resample Balance +- Channel width + + OverwriteDialog @@ -7210,7 +7455,7 @@ fueran posibles, al resolver la ruta de un archvo. Weight *: - Grosor *: + Grosor *: OpenToonz can use FFmpeg for additional file formats. @@ -7318,6 +7563,55 @@ También, se establecerá el destino inicial de salida para las nuevas escenas e Compact Compacto + + Saving + + + + Use Onion Skin Colors for Reference Drawings of Shift and Trace + + + + Tablet Settings + + + + Enable Windows Ink Support* (EXPERIMENTAL) + + + + Constant + + + + Exponential + + + + Expression + + + + File + Archivo + + + Style *: + + + + Matte color is used for background when overwriting raster levels with transparent pixels +in non alpha-enabled image format. + + + + Matte color: + + + + Current Column Color: + + PreferencesPopup::FormatProperties @@ -8176,7 +8470,7 @@ Algunos niveles no han sido cargados porque su versión no es soportada. The Revert to Last Saved command is not supported for the current selection. - El comando Revertir a última versión guardada no es soportado para la selección actual. + El comando Revertir a última versión guardada no es soportado para la selección actual. The selected column is empty. @@ -9198,6 +9492,67 @@ Allow duplicate? Nothing to replace: no cells or columns selected. Nada que reemplazar: no se han seleccionado acetatos o columnas. + + Couldn't load %1 + + + + Apply Antialias + Aplicar suavizado de bordes + + + The Reload command is not supported for the current selection. + + + + Error + + + + No Palette loaded. + + + + A separation task is in progress! wait until it stops or cancel it + + + + Duplicate Frame in XSheet + + + + Please enable "Sync Level Strip Drawing Number Changes with the XSheet" preference option +to use the duplicate command in the xsheet / timeline. + + + + Please select only one layer to duplicate a frame. + + + + Please select only one frame to duplicate. + + + + Timeline + + + + The qualifier %1 is not a valid key name. Skipping. + + + + Clear All Onion Skin Markers + + + + Clear All Fixed Onion Skin Markers + + + + Clear All Relative Onion Skin Markers + + ReframePopup @@ -10188,6 +10543,13 @@ Por favor enviar o revertir los cambios antes. + SaveBoardPresetFilePopup + + Save Clapperboard Settings As Preset + + + + SaveCurvePopup Save Curve @@ -10594,6 +10956,172 @@ Por favor enviar o revertir los cambios antes. + SeparateColorsPopup + + Auto + Auto + + + Preview + + + + Separate + + + + Close + Cerrar + + + Sub Color 3: + + + + Alpha Matting + + + + Main + + + + Sub1 + + + + Sub2 + + + + Sub3 + + + + Pick Color + + + + Show Mask + + + + Show Alpha + + + + Preview Frame: + + + + Paper Color: + + + + Main Color: + + + + Sub Color 1: + + + + Sub Color 2: + + + + Sub Adjust: + + + + Border Smooth: + + + + Mask Threshold: + + + + Mask Radius: + + + + Start: + + + + End: + + + + Format: + Formato: + + + Save in: + + + + File Suffix: + + + + Cancel + + + + Separate by colors ... + + + + Separate 1 Level + + + + Separate %1 Levels + + + + Critical + + + + Failed to access the destination folder! + + + + Separating %1 + + + + Converting level %1 of %2: %3 + Convirtiendo el nivel %1 de %2: %3 + + + + SeparateSwatch + + Sub Color 3 + + + + Original + + + + Main Color + + + + Sub Color 1 + + + + Sub Color 2 + + + + ShortcutPopup Configure Shortcuts @@ -11975,6 +12503,10 @@ Por favor ver la guía de usuario para obtener más detalles. Filter: Filtro: + + Opacity: + + XsheetGUI::NoteArea @@ -11994,6 +12526,22 @@ Por favor ver la guía de usuario para obtener más detalles. 3sec Sheet pág de 3" + + Toggle Xsheet/Timeline + + + + Add New Memo + + + + Previous Memo + + + + Next Memo + + XsheetGUI::NotePopup @@ -12068,6 +12616,32 @@ Por favor ver la guía de usuario para obtener más detalles. Set Auto Markers Definir marcadores automáticamente + + Click to Reset Shift & Trace Markers to Neighbor Frames +Hold F2 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F1 Key on the Viewer to Show This Frame Only + + + + Click to Hide This Frame from Shift & Trace +Hold F3 Key on the Viewer to Show This Frame Only + + + + Click to Move Shift & Trace Marker + + + + + XsheetGUI::SoundColumnPopup + + Volume: + + XsheetGUI::Toolbar diff --git a/toonz/sources/translations/spanish/toonzqt.ts b/toonz/sources/translations/spanish/toonzqt.ts index db005b2..29679bf 100644 --- a/toonz/sources/translations/spanish/toonzqt.ts +++ b/toonz/sources/translations/spanish/toonzqt.ts @@ -256,7 +256,7 @@ Es posible que el archivo de dicho ajuste se encuentre corrupto. &Open Subxsheet - &Entrar en sub-planilla + &Entrar en sub-planilla @@ -697,6 +697,17 @@ Es posible que el archivo de dicho ajuste se encuentre corrupto. + FontParamField + + Style: + + + + Size: + + + + FrameNavigator Previous Frame @@ -1086,7 +1097,7 @@ Es posible que el archivo de dicho ajuste se encuentre corrupto. &Open Subxsheet - &Entrar en sub-planilla + &Entrar en sub-planilla &Uncache Fx @@ -1206,6 +1217,13 @@ Es posible que el archivo de dicho ajuste se encuentre corrupto. + FxSchematicOutputNode + + Output + Salida + + + FxSchematicPort &Disconnect from Xsheet @@ -1238,6 +1256,13 @@ Seleccionar los nodos de efecto y sus vínculos relacionados antes de copiar o c + FxSchematicXSheetNode + + XSheet + Planilla + + + FxSettings &Camera Preview @@ -2194,6 +2219,10 @@ La segunda línea debería tener la forma "Mesh [profundidad de bits de ent &Swtich output port display mode &Cambiar visualización de puertos de salida + + &Toggle node icons + + SchematicWindowEditor diff --git a/toonz/sources/xdg-data/io.github.OpenToonz.appdata.xml b/toonz/sources/xdg-data/io.github.OpenToonz.appdata.xml new file mode 100644 index 0000000..9efa205 --- /dev/null +++ b/toonz/sources/xdg-data/io.github.OpenToonz.appdata.xml @@ -0,0 +1,32 @@ + + + io.github.OpenToonz + io.github.OpenToonz.desktop + OpenToonz + CC0-1.0 + BSD-3-Clause + DWANGO Co., Ltd. + 2D animation + +

+ This is software for producing a 2D animation. +

+

+ It is based on the software "Toonz", which was developed + by Digital Video S.p.A. in Italy, customized by Studio Ghibli, + and has been used for creating its works for many years. + Dwango launched the OpenToonz project in cooperation + with Digital Video and Studio Ghibli. +

+
+ https://opentoonz.github.io + + + https://raw.githubusercontent.com/flathub/io.github.OpenToonz/master/screenshot1.png + + + + + + +
diff --git a/toonz/sources/xdg-data/io.github.OpenToonz.desktop b/toonz/sources/xdg-data/io.github.OpenToonz.desktop new file mode 100644 index 0000000..622ab68 --- /dev/null +++ b/toonz/sources/xdg-data/io.github.OpenToonz.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Application +Name=OpenToonz +Icon=io.github.OpenToonz +Exec=opentoonz +Categories=Graphics; diff --git a/toonz/sources/xdg-data/io.github.OpenToonz.png b/toonz/sources/xdg-data/io.github.OpenToonz.png new file mode 100644 index 0000000..8fbb30a Binary files /dev/null and b/toonz/sources/xdg-data/io.github.OpenToonz.png differ