diff --git a/doc/how_to_build_linux.md b/doc/how_to_build_linux.md index c3db2b2..e353f9a 100644 --- a/doc/how_to_build_linux.md +++ b/doc/how_to_build_linux.md @@ -33,7 +33,7 @@ $ rpm ... (it may include some useless packages) ``` -dnf install gcc gcc-c++ automake git cmake boost boost-devel SuperLU SuperLU-devel lz4-devel libusb-devel lzo-devel libjpeg-turbo-devel GLEW libGLEW freeglut-devel freeglut SDL2 SDL2-devel freetype-devel libpng-devel qt5-base qt5-qtbase-devel qt5-qtsvg qt5-qtsvg-devel qt5-qtscript qt5-qtscript-devel qt5-qttools qt5-qttools-devel blas blas-devel +dnf install gcc gcc-c++ automake git cmake boost boost-devel SuperLU SuperLU-devel lz4-devel lzma libusb-devel lzo-devel libjpeg-turbo-devel libGLEW glew-devel freeglut-devel freeglut SDL2 SDL2-devel freetype-devel libpng-devel qt5-qtbase-devel qt5-qtsvg qt5-qtsvg-devel qt5-qtscript qt5-qtscript-devel qt5-qttools qt5-qttools-devel qt5-qtmultimedia-devel blas blas-devel ``` ### Installing required packages on ArchLinux @@ -53,7 +53,7 @@ Notes: ### Installing required packages on openSUSE ``` -zypper in boost-devel git cmake gcc-c++ freeglut-devel freetype2-devel glew-devel libjpeg-devel liblz4-devel libqt5-linguist-devel libQt5OpenGL5 libqt5-qtbase-devel libqt5-qtscript-devel libqt5-qtsvg-devel lzo-devel libusb-devel openblas-devel SDL2-devel superlu-devel zlib-devel +zypper in boost-devel cmake freeglut-devel freetype2-devel gcc-c++ glew-devel libQt5OpenGL-devel libSDL2-devel libjpeg-devel liblz4-devel libpng16-compat-devel libqt5-linguist-devel libqt5-qtbase-devel libqt5-qtmultimedia-devel libqt5-qtscript-devel libqt5-qtsvg-devel libtiff-devel libusb-devel lzo-devel openblas-devel pkgconfig sed superlu-devel zlib-devel ``` ## Build instructions @@ -158,3 +158,15 @@ Then you can launch OpenToonz by running `/opt/opentoonz/bin/opentoonz`. You can change the installation path by modifying the `CMAKE_INSTALL_PREFIX` CMake variable. +---- + +# Linux Package Definitions + +It may be helpful to use existing packages as a reference when creating a package for your own distribution. + +- ArchLinux (AUR): + https://aur.archlinux.org/packages/opentoonz-git/ + +- App-Image (Portable): + https://github.com/morevnaproject/morevna-builds + diff --git a/doc/how_to_build_win.md b/doc/how_to_build_win.md index 94eaf9e..376e47e 100644 --- a/doc/how_to_build_win.md +++ b/doc/how_to_build_win.md @@ -63,13 +63,6 @@ Rename the following files: - `$opentoonz/thirdparty/libpng-1.6.21/scripts/pnglibconf.h.prebuilt` to `$opentoonz/thirdparty/libpng-1.6.21/pnglibconf.h` - Note that the destination is a different folder for the last file. -Add a guard for snprintf at tif_config.h(50): -``` -+#if _MSC_VER < 1900 -#define snprintf _snprintf -+#endif -``` - ## Building 1. Open `$opentoonz/toonz/build/OpenToonz.sln` and change to `Release` 2. The output will be in `$opentoonz/toonz/build/Release` diff --git a/doc/how_to_build_win_ja.md b/doc/how_to_build_win_ja.md index 493e1f4..5bd2847 100644 --- a/doc/how_to_build_win_ja.md +++ b/doc/how_to_build_win_ja.md @@ -57,13 +57,6 @@ Visual Studio 2015 と Qt 5.6 でビルドできることを確認していま� - `$opentoonz/thirdparty/tiff-4.0.3/libtiff/tiffconf.vc.h` → `$opentoonz/thirdparty/tiff-4.0.3/libtiff/tiffconf.h` - `$opentoonz/thirdparty/libpng-1.6.21/scripts/pnglibconf.h.prebuilt` → `$opentoonz/thirdparty/libpng-1.6.21/pnglibconf.h` -`tif_config.h` の 50 行目あたりに下記の修正を加えます: -``` -+#if _MSC_VER < 1900 -#define snprintf _snprintf -+#endif -``` - ## ビルド 1. `$opentoonz/toonz/build/OpenToonz.sln` を開いて Release 構成を選択してビルドします 2. `$opentoonz/toonz/build/Release` にファイルが生成されます diff --git a/stuff/config/qss/gray_048/gray_048.less b/stuff/config/qss/gray_048/gray_048.less index 0590e85..c170ed2 100644 --- a/stuff/config/qss/gray_048/gray_048.less +++ b/stuff/config/qss/gray_048/gray_048.less @@ -748,7 +748,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ #CleanupSettingsFrame, #LoadLevelFrame, -#SolidLineFrame{ +#SolidLineFrame { border: 1px solid @m_baseTxtColor; } @@ -1365,4 +1365,15 @@ QDialog #dialogButtonFrame { #LargeSizedText { font-size: 17px; +} + +#GearButton { + qproperty-icon: url("@{image_url}/gear.png"); +} + +#StartupLabel { + padding: 3px; + &:hover { + .baseBG(light, 10%); + } } \ No newline at end of file diff --git a/stuff/config/qss/gray_048/gray_048.qss b/stuff/config/qss/gray_048/gray_048.qss index 6936166..0c17daf 100644 --- a/stuff/config/qss/gray_048/gray_048.qss +++ b/stuff/config/qss/gray_048/gray_048.qss @@ -1369,5 +1369,14 @@ QDialog #dialogButtonFrame { #LargeSizedText { font-size: 17px; } +#GearButton { + qproperty-icon: url("../gray_072/imgs/gear.png"); +} +#StartupLabel { + padding: 3px; +} +#StartupLabel:hover { + background-color: #4a4a4a; +} //# sourceMappingURL=gray_048.qss.map \ No newline at end of file diff --git a/stuff/config/qss/gray_048/gray_048_mac.qss b/stuff/config/qss/gray_048/gray_048_mac.qss index 7c6a503..1217245 100644 --- a/stuff/config/qss/gray_048/gray_048_mac.qss +++ b/stuff/config/qss/gray_048/gray_048_mac.qss @@ -1369,5 +1369,14 @@ QDialog #dialogButtonFrame { #LargeSizedText { font-size: 17px; } +#GearButton { + qproperty-icon: url("../gray_072/imgs/gear.png"); +} +#StartupLabel { + padding: 3px; +} +#StartupLabel:hover { + background-color: #4a4a4a; +} //# sourceMappingURL=gray_048_mac.qss.map \ No newline at end of file diff --git a/stuff/config/qss/gray_072/gray_072.less b/stuff/config/qss/gray_072/gray_072.less index c918bcf..60044ee 100644 --- a/stuff/config/qss/gray_072/gray_072.less +++ b/stuff/config/qss/gray_072/gray_072.less @@ -747,7 +747,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ #CleanupSettingsFrame, #LoadLevelFrame, -#SolidLineFrame{ +#SolidLineFrame { border: 1px solid @m_baseTxtColor; } @@ -1365,4 +1365,15 @@ QDialog #dialogButtonFrame { #LargeSizedText { font-size: 17px; +} + +#GearButton { + qproperty-icon: url("@{image_url}/gear.png"); +} + +#StartupLabel { + padding: 3px; + &:hover { + .baseBG(light, 10%); + } } \ No newline at end of file diff --git a/stuff/config/qss/gray_072/gray_072.qss b/stuff/config/qss/gray_072/gray_072.qss index 69c5a4d..824600c 100644 --- a/stuff/config/qss/gray_072/gray_072.qss +++ b/stuff/config/qss/gray_072/gray_072.qss @@ -1369,5 +1369,14 @@ QDialog #dialogButtonFrame { #LargeSizedText { font-size: 17px; } +#GearButton { + qproperty-icon: url("imgs/gear.png"); +} +#StartupLabel { + padding: 3px; +} +#StartupLabel:hover { + background-color: #626262; +} //# sourceMappingURL=gray_072.qss.map \ No newline at end of file diff --git a/stuff/config/qss/gray_072/gray_072_mac.qss b/stuff/config/qss/gray_072/gray_072_mac.qss index 182e253..3c89f26 100644 --- a/stuff/config/qss/gray_072/gray_072_mac.qss +++ b/stuff/config/qss/gray_072/gray_072_mac.qss @@ -1369,5 +1369,14 @@ QDialog #dialogButtonFrame { #LargeSizedText { font-size: 17px; } +#GearButton { + qproperty-icon: url("imgs/gear.png"); +} +#StartupLabel { + padding: 3px; +} +#StartupLabel:hover { + background-color: #626262; +} //# sourceMappingURL=gray_072_mac.qss.map \ No newline at end of file diff --git a/stuff/config/qss/gray_072/imgs/gear.png b/stuff/config/qss/gray_072/imgs/gear.png new file mode 100644 index 0000000..7e07631 Binary files /dev/null and b/stuff/config/qss/gray_072/imgs/gear.png differ diff --git a/stuff/config/qss/gray_128/gray_128.less b/stuff/config/qss/gray_128/gray_128.less index 2c13e25..168a281 100644 --- a/stuff/config/qss/gray_128/gray_128.less +++ b/stuff/config/qss/gray_128/gray_128.less @@ -595,7 +595,7 @@ DvDirTreeView { /*---------------------------------------------------------------------------*/ #CleanupSettingsFrame, #LoadLevelFrame, -#SolidLineFrame{ +#SolidLineFrame { border: 1px solid rgb(20,20,20); } @@ -1190,4 +1190,15 @@ QDialog #dialogButtonFrame { #LargeSizedText { font-size: 17px; +} + +#GearButton { + qproperty-icon: url("@{image_url}/gear.png"); +} + +#StartupLabel { + padding: 3px; + &:hover { + .baseBG(light, 10%); + } } \ No newline at end of file diff --git a/stuff/config/qss/gray_128/gray_128.qss b/stuff/config/qss/gray_128/gray_128.qss index 1f3a66e..ee88456 100644 --- a/stuff/config/qss/gray_128/gray_128.qss +++ b/stuff/config/qss/gray_128/gray_128.qss @@ -1108,5 +1108,14 @@ QDialog #dialogButtonFrame { #LargeSizedText { font-size: 17px; } +#GearButton { + qproperty-icon: url("imgs/gear.png"); +} +#StartupLabel { + padding: 3px; +} +#StartupLabel:hover { + background-color: #9a9a9a; +} //# sourceMappingURL=gray_128.qss.map \ No newline at end of file diff --git a/stuff/config/qss/gray_128/gray_128_mac.qss b/stuff/config/qss/gray_128/gray_128_mac.qss index f66c40d..a7b90c2 100644 --- a/stuff/config/qss/gray_128/gray_128_mac.qss +++ b/stuff/config/qss/gray_128/gray_128_mac.qss @@ -1108,5 +1108,14 @@ QDialog #dialogButtonFrame { #LargeSizedText { font-size: 17px; } +#GearButton { + qproperty-icon: url("imgs/gear.png"); +} +#StartupLabel { + padding: 3px; +} +#StartupLabel:hover { + background-color: #9a9a9a; +} //# sourceMappingURL=gray_128_mac.qss.map \ No newline at end of file diff --git a/stuff/config/qss/gray_128/imgs/gear.png b/stuff/config/qss/gray_128/imgs/gear.png new file mode 100644 index 0000000..36477dd Binary files /dev/null and b/stuff/config/qss/gray_128/imgs/gear.png differ diff --git a/stuff/profiles/layouts/rooms/Default/menubar_template.xml b/stuff/profiles/layouts/rooms/Default/menubar_template.xml index 5df924e..6c9f3b8 100644 --- a/stuff/profiles/layouts/rooms/Default/menubar_template.xml +++ b/stuff/profiles/layouts/rooms/Default/menubar_template.xml @@ -2,9 +2,9 @@ MI_NewScene MI_LoadScene + MI_SaveAll MI_SaveScene MI_SaveSceneAs - MI_SaveAll MI_OpenRecentScene MI_RevertScene @@ -13,6 +13,7 @@ MI_NewLevel MI_LoadLevel + MI_SaveAllLevels MI_SaveLevel MI_SaveLevelAs MI_ExportLevel @@ -233,6 +234,7 @@ MI_ResetRoomLayout + MI_StartupPopup MI_About \ No newline at end of file diff --git a/stuff/profiles/layouts/rooms/StudioGhibli/menubar_template.xml b/stuff/profiles/layouts/rooms/StudioGhibli/menubar_template.xml index eee1faf..b78b58c 100644 --- a/stuff/profiles/layouts/rooms/StudioGhibli/menubar_template.xml +++ b/stuff/profiles/layouts/rooms/StudioGhibli/menubar_template.xml @@ -13,6 +13,7 @@ MI_NewLevel MI_LoadLevel + MI_SaveAllLevels MI_SaveLevel MI_SaveLevelAs MI_ExportLevel diff --git a/stuff/profiles/layouts/shortcuts/defopentoonz.ini b/stuff/profiles/layouts/shortcuts/defopentoonz.ini new file mode 100644 index 0000000..ebb88c6 --- /dev/null +++ b/stuff/profiles/layouts/shortcuts/defopentoonz.ini @@ -0,0 +1,366 @@ +[shortcuts] +MI_Clear=Del +MI_OnionSkin=/ +A_DecreaseBrushHardness= +A_DecreaseMaxBrushThickness=U +A_DecreaseMinBrushThickness=H +A_FxSchematicToggle= +A_IncreaseBrushHardness= +A_IncreaseMaxBrushThickness=I +A_IncreaseMinBrushThickness=J +A_ToolOption_AutoGroup= +A_ToolOption_AutoSelect%3AColumn= +A_ToolOption_AutoSelect%3ANone= +A_ToolOption_AutoSelect%3APegbar= +A_ToolOption_AutoSelectDrawing= +A_ToolOption_Autofill= +A_ToolOption_BreakSharpAngles= +A_ToolOption_BrushPreset= +A_ToolOption_EditToolActiveAxis= +A_ToolOption_EditToolActiveAxis%3ACenter= +A_ToolOption_EditToolActiveAxis%3APosition= +A_ToolOption_EditToolActiveAxis%3ARotation= +A_ToolOption_EditToolActiveAxis%3AScale= +A_ToolOption_EditToolActiveAxis%3AShear= +A_ToolOption_FrameRange=F6 +A_ToolOption_GeometricEdge= +A_ToolOption_GeometricShape= +A_ToolOption_GlobalKey= +A_ToolOption_IK= +A_ToolOption_Invert= +A_ToolOption_JoinVectors= +A_ToolOption_Manual= +A_ToolOption_Meshify= +A_ToolOption_Mode= +A_ToolOption_Mode%3AAreas= +A_ToolOption_Mode%3ALines= +A_ToolOption_Mode%3ALines%20%26%20Areas= +A_ToolOption_OnionSkin= +A_ToolOption_Orientation= +A_ToolOption_PencilMode= +A_ToolOption_PickScreen= +A_ToolOption_PreserveThickness= +A_ToolOption_PressureSensitivity=Shift+P +A_ToolOption_SegmentInk=F8 +A_ToolOption_Selective=F7 +A_ToolOption_ShowOnlyActiveSkeleton= +A_ToolOption_SkeletonMode%3AAnimate= +A_ToolOption_SkeletonMode%3ABuild%20Skeleton= +A_ToolOption_SkeletonMode%3AInverse%20Kinematics= +A_ToolOption_Smooth= +A_ToolOption_Snap= +A_ToolOption_Type= +A_ToolOption_Type%3AFreehand= +A_ToolOption_Type%3ANormal= +A_ToolOption_Type%3APolyline= +A_ToolOption_Type%3ARectangular=F5 +A_ToolOption_TypeFont= +A_ToolOption_TypeSize= +A_ToolOption_TypeStyle= +MI_ACheck= +MI_About= +MI_ActivateAllColumns= +MI_ActivateSelectedColumns= +MI_ActivateThisColumnOnly= +MI_AddFrames= +MI_AddToBatchCleanupList= +MI_AddToBatchRenderList= +MI_AdjustLevels= +MI_AdjustThickness= +MI_Antialias= +MI_ApplyMatchLines= +MI_AutoFillToggle=Shift+A +MI_Autocenter= +MI_Autorenumber= +MI_BCheck= +MI_Binarize= +MI_BlendColors= +MI_BlueChannel= +MI_BlueChannelGreyscale= +MI_BrightnessAndContrast= +MI_BringForward=] +MI_BringToFront=Ctrl+] +MI_CameraSettings= +MI_CameraStage= +MI_CameraTest= +MI_CanvasSize= +MI_Cleanup= +MI_CleanupPreview= +MI_CleanupSettings= +MI_ClearRecentImage= +MI_ClearRecentLevel= +MI_ClearRecentScene= +MI_CloneChild= +MI_CloneLevel= +MI_ClonePreview= +MI_CloseChild= +MI_Collapse= +MI_CollectAssets= +MI_CompareToSnapshot= +MI_ConvertFileWithInput= +MI_ConvertFiles= +MI_ConvertToVectors= +MI_Copy=Ctrl+C +MI_Cut=Ctrl+X +MI_DeactivateAllColumns= +MI_DeactivateSelectedColumns= +MI_DeactivateUpperColumns= +MI_DecreaseStep=";" +MI_DefineScanner= +MI_DeleteInk= +MI_DeleteMatchLines= +MI_DisableAllColumns= +MI_DisableSelectedColumns= +MI_DockingCheck= +MI_DrawingSubBackward=Q +MI_DrawingSubForward=W +MI_DrawingSubGroupBackward=Alt+Q +MI_DrawingSubGroupForward=Alt+W +MI_Dup= +MI_Duplicate=D +MI_DuplicateFile= +MI_Each2= +MI_Each3= +MI_Each4= +MI_EditLevel= +MI_EditShift= +MI_EnableAllColumns= +MI_EnableSelectedColumns= +MI_EnableThisColumnOnly= +MI_EnterGroup= +MI_EraseUnusedStyles= +MI_ExitGroup= +MI_ExplodeChild= +MI_ExportLevel= +MI_ExportScenes= +MI_ExposeResource= +MI_FieldGuide=Shift+G +MI_FileInfo= +MI_FillAreas= +MI_FillLines= +MI_FirstFrame="Alt+," +MI_FoldColumns= +MI_FrezzePreview= +MI_FullScreenWindow=Ctrl+` +MI_FxParamEditor=Ctrl+K +MI_GCheck= +MI_GetColorFromStudioPalette= +MI_GreenChannel= +MI_GreenChannelGreyscale= +MI_Group=Ctrl+G +MI_Histogram= +MI_ICheck= +MI_IOnly= +MI_ImportMagpieFile= +MI_ImportScenes= +MI_IncreaseStep="'" +MI_Increment= +MI_Ink1Check= +MI_Insert=Ins +MI_InsertFx=Ctrl+F +MI_InsertGlobalKeyframe= +MI_InsertSceneFrame= +MI_InvertKeyframeSelection= +MI_InvertSelection= +MI_LastFrame=Alt+. +MI_LevelSettings= +MI_LinesFade= +MI_Link= +MI_LoadColorModel= +MI_LoadFolder= +MI_LoadLevel= +MI_LoadScene=Ctrl+L +MI_LoadSubSceneFile= +MI_LockAllColumns=Ctrl+Alt+Shift+L +MI_LockSelectedColumns=Ctrl+Shift+L +MI_LockThisColumnOnly=Shift+L +MI_Loop=L +MI_MatteChannel= +MI_MaximizePanel=` +MI_MergeCmapped= +MI_MergeColumns= +MI_MergeFrames= +MI_NewLevel=Alt+N +MI_NewOutputFx= +MI_NewProject= +MI_NewScene=Ctrl+N +MI_NextDrawing=. +MI_NextFrame=Shift+. +MI_NextStep= +MI_NoShift= +MI_OpacityCheck=1 +MI_OpenBatchServers= +MI_OpenChild= +MI_OpenCleanupSettings= +MI_OpenColorModel= +MI_OpenComboViewer= +MI_OpenFileBrowser= +MI_OpenFileBrowser2= +MI_OpenFileViewer= +MI_OpenFilmStrip= +MI_OpenFunctionEditor= +MI_OpenHistoryPanel=Ctrl+H +MI_OpenLevelView= +MI_OpenPalette= +MI_OpenPltGizmo= +MI_OpenRecentLevel= +MI_OpenRecentScene= +MI_OpenSchematic= +MI_OpenScriptConsole= +MI_OpenStudioPalette= +MI_OpenStyleControl= +MI_OpenTMessage= +MI_OpenTasks= +MI_OpenToolOptionBar= +MI_OpenToolbar= +MI_OpenXshView= +MI_OutputSettings=Ctrl+O +MI_OverwritePalette= +MI_PCheck= +MI_Paste=Ctrl+V +MI_PasteColors= +MI_PasteInto= +MI_PasteNames= +MI_PasteValues= +MI_Pause= +MI_PencilTest= +MI_PickStyleAreas= +MI_PickStyleLines= +MI_Play=P +MI_Preferences=Ctrl+U +MI_PrevDrawing="," +MI_PrevFrame="Shift+," +MI_PrevStep= +MI_Preview=Ctrl+R +MI_PreviewFx= +MI_PreviewSettings= +MI_Print=Ctrl+P +MI_PrintXsheet= +MI_ProjectSettings= +MI_Quit=Ctrl+Q +MI_Random= +MI_RasterizePli= +MI_RedChannel= +MI_RedChannelGreyscale= +MI_Redo=Ctrl+Y +MI_Reframe1= +MI_Reframe2= +MI_Reframe3= +MI_Reframe4= +MI_RefreshTree= +MI_RegenerateFramePr= +MI_RegeneratePreview= +MI_ReloadStyle= +MI_RemoveEndpoints= +MI_RemoveGlobalKeyframe= +MI_RemoveLevel= +MI_RemoveSceneFrame= +MI_RemoveUnused= +MI_Render=Ctrl+Shift+R +MI_Renumber= +MI_ReplaceLevel= +MI_ReplaceParentDirectory= +MI_Resequence= +MI_ResetInterpolation= +MI_ResetRoomLayout= +MI_ResetScanCropbox= +MI_ResetShift= +MI_ResetStep= +MI_Reverse= +MI_RevertScene= +MI_RevertToCleanedUp= +MI_RevertToLastSaved= +MI_Rolldown= +MI_Rollup= +MI_RunScript= +MI_SafeArea= +MI_SaveAll=Ctrl+S +MI_SaveDefaultSettings= +MI_SaveLevel= +MI_SaveLevelAs= +MI_SavePaletteAs= +MI_SavePreset= +MI_SavePreviewedFrames= +MI_SaveScene=Ctrl+Shift+S +MI_SaveSceneAs= +MI_SaveSubxsheetAs= +MI_Scan= +MI_ScanSettings= +MI_SceneSettings= +MI_SelectAll=Ctrl+A +MI_SelectAllKeyframes= +MI_SelectAllKeyframesNotAfter= +MI_SelectAllKeyframesNotBefore= +MI_SelectColumnKeyframes= +MI_SelectFollowingKeysInColumn= +MI_SelectFollowingKeysInRow= +MI_SelectPreviousKeysInColumn= +MI_SelectPreviousKeysInRow= +MI_SelectRowKeyframes= +MI_SendBack=Ctrl+[ +MI_SendBackward=[ +MI_SetAcceleration= +MI_SetConstantSpeed= +MI_SetDeceleration= +MI_SetKeyframes=Z +MI_SetScanCropbox= +MI_ShiftTrace= +MI_ShortcutPopup= +MI_ShowFolderContents= +MI_Step2= +MI_Step3= +MI_Step4= +MI_SwapEnabledColumns= +MI_Swing= +MI_TCheck= +MI_TimeStretch= +MI_ToggleColumnLocks= +MI_ToggleColumnsActivation= +MI_ToggleEditInPlace= +MI_Tracking= +MI_Undo=Ctrl+Z +MI_Ungroup=Ctrl+Shift+G +MI_UnlockAllColumns=Ctrl+Alt+Shift+U +MI_UnlockSelectedColumns=Ctrl+Shift+U +MI_ViewBBox= +MI_ViewCamera= +MI_ViewColorcard= +MI_ViewFile= +MI_ViewGuide= +MI_ViewRuler= +MI_ViewTable= +MI_ZeroThick=Shift+/ +T_ActualPixelSize=N +T_Bender= +T_Brush=B +T_ControlPointEditor=C +T_Cutter= +T_Edit=E +T_Eraser=A +T_Fill=F +T_Finger= +T_Geometric=G +T_Hand=Space +T_Hook=O +T_Iron= +T_Magnet= +T_PaintBrush= +T_Pinch=M +T_Plastic=X +T_Pump= +T_RGBPicker=R +T_Rotate=Ctrl+Space +T_Ruler= +T_Selection=S +T_ShowHideFullScreen=Alt+F +T_Skeleton=V +T_StylePicker=K +T_Tape=T +T_Tracker= +T_Type=Y +T_Zoom=Shift+Space +T_ZoomFit=9 +T_ZoomReset=0 +T_Zoomin=+ +T_Zoomout=- +MI_LoadRecentImage= diff --git a/stuff/profiles/layouts/shortcuts/otadobe.ini b/stuff/profiles/layouts/shortcuts/otadobe.ini new file mode 100644 index 0000000..7a1b172 --- /dev/null +++ b/stuff/profiles/layouts/shortcuts/otadobe.ini @@ -0,0 +1,366 @@ +[shortcuts] +MI_LoadRecentImage= +A_ToolOption_FrameRange= +A_ToolOption_SegmentInk= +A_ToolOption_Selective= +A_ToolOption_Type%3ARectangular= +MI_BringForward=Ctrl+Up +MI_BringToFront=Ctrl+Shift+Up +MI_Clear=Delete +MI_Copy=Ctrl+C +MI_Cut=Ctrl+X +MI_DrawingSubBackward=[ +MI_DrawingSubForward=] +MI_DrawingSubGroupBackward=Ctrl+[ +MI_DrawingSubGroupForward=Ctrl+] +MI_Duplicate= +MI_FullScreenWindow=Ctrl+F +MI_FxParamEditor= +MI_Group=Ctrl+G +MI_Insert=Ins +MI_InsertFx= +MI_LoadScene=Ctrl+O +MI_MaximizePanel= +MI_NewScene=Ctrl+N +MI_NextDrawing=G +MI_NextFrame=. +MI_OpacityCheck= +MI_Paste=Ctrl+V +MI_PrevDrawing=F +MI_PrevFrame="," +MI_Preview=Alt+P +MI_Quit=Ctrl+Q +MI_Redo=Ctrl+Y +MI_SaveScene=Ctrl+Shift+S +MI_SaveSceneAs=Ctrl+Alt+Shift+S +MI_SelectAll=Shift+A +MI_SendBack=Ctrl+Shift+Down +MI_SendBackward=Ctrl+Down +MI_Undo=Ctrl+Z +MI_ZeroThick=D +T_ActualPixelSize= +T_Brush=Alt+B +T_ControlPointEditor=Alt+A +T_Edit=Alt+Q +T_Eraser=Alt+E +T_Fill=Alt+K +T_Geometric=Atl+R +T_Hand= +T_Pinch= +T_Rotate= +T_Selection=Alt+V +T_StylePicker=Alt+I +T_Tape=Alt+C +T_Type= +T_Zoom=Alt+Z +T_ZoomReset=Shift+Z +T_Zoomin=Ctrl+= +T_Zoomout=Ctrl+- +A_DecreaseBrushHardness= +A_DecreaseMaxBrushThickness= +A_DecreaseMinBrushThickness= +A_FxSchematicToggle= +A_IncreaseBrushHardness= +A_IncreaseMaxBrushThickness= +A_IncreaseMinBrushThickness= +A_ToolOption_AutoGroup= +A_ToolOption_AutoSelect%3AColumn= +A_ToolOption_AutoSelect%3ANone= +A_ToolOption_AutoSelect%3APegbar= +A_ToolOption_AutoSelectDrawing= +A_ToolOption_Autofill= +A_ToolOption_BreakSharpAngles= +A_ToolOption_BrushPreset= +A_ToolOption_EditToolActiveAxis= +A_ToolOption_EditToolActiveAxis%3ACenter= +A_ToolOption_EditToolActiveAxis%3APosition= +A_ToolOption_EditToolActiveAxis%3ARotation= +A_ToolOption_EditToolActiveAxis%3AScale= +A_ToolOption_EditToolActiveAxis%3AShear= +A_ToolOption_GeometricEdge= +A_ToolOption_GeometricShape= +A_ToolOption_GlobalKey= +A_ToolOption_IK=Alt+8 +A_ToolOption_Invert= +A_ToolOption_JoinVectors= +A_ToolOption_Manual= +A_ToolOption_Meshify= +A_ToolOption_Mode= +A_ToolOption_Mode%3AAreas= +A_ToolOption_Mode%3ALines= +A_ToolOption_Mode%3ALines%20%26%20Areas= +A_ToolOption_OnionSkin= +A_ToolOption_Orientation= +A_ToolOption_PencilMode= +A_ToolOption_PickScreen= +A_ToolOption_PreserveThickness= +A_ToolOption_PressureSensitivity= +A_ToolOption_ShowOnlyActiveSkeleton= +A_ToolOption_SkeletonMode%3AAnimate= +A_ToolOption_SkeletonMode%3ABuild%20Skeleton= +A_ToolOption_SkeletonMode%3AInverse%20Kinematics= +A_ToolOption_Smooth= +A_ToolOption_Snap= +A_ToolOption_Type= +A_ToolOption_Type%3AFreehand= +A_ToolOption_Type%3ANormal= +A_ToolOption_Type%3APolyline= +A_ToolOption_TypeFont= +A_ToolOption_TypeSize= +A_ToolOption_TypeStyle= +MI_ACheck= +MI_About= +MI_ActivateAllColumns= +MI_ActivateSelectedColumns= +MI_ActivateThisColumnOnly= +MI_AddFrames=Ctrl+H +MI_AddToBatchCleanupList= +MI_AddToBatchRenderList= +MI_AdjustLevels= +MI_AdjustThickness= +MI_Antialias= +MI_ApplyMatchLines= +MI_AutoFillToggle= +MI_Autocenter= +MI_Autorenumber= +MI_BCheck= +MI_Binarize= +MI_BlendColors= +MI_BlueChannel= +MI_BlueChannelGreyscale= +MI_BrightnessAndContrast= +MI_CameraSettings= +MI_CameraStage= +MI_CameraTest= +MI_CanvasSize= +MI_Cleanup= +MI_CleanupPreview= +MI_CleanupSettings= +MI_ClearRecentImage= +MI_ClearRecentLevel= +MI_ClearRecentScene= +MI_CloneChild= +MI_CloneLevel= +MI_ClonePreview= +MI_CloseChild= +MI_Collapse= +MI_CollectAssets= +MI_CompareToSnapshot= +MI_ConvertFileWithInput= +MI_ConvertFiles= +MI_ConvertToVectors= +MI_DeactivateAllColumns= +MI_DeactivateSelectedColumns=Alt+H +MI_DeactivateUpperColumns= +MI_DecreaseStep= +MI_DefineScanner= +MI_DeleteInk= +MI_DeleteMatchLines= +MI_DisableAllColumns= +MI_DisableSelectedColumns= +MI_DockingCheck= +MI_Dup= +MI_DuplicateFile= +MI_Each2= +MI_Each3= +MI_Each4= +MI_EditLevel= +MI_EditShift= +MI_EnableAllColumns=Alt+Shift+H +MI_EnableSelectedColumns= +MI_EnableThisColumnOnly= +MI_EnterGroup=Ctrl+Return +MI_EraseUnusedStyles= +MI_ExitGroup=Backspace +MI_ExplodeChild=Ctrl+B +MI_ExportLevel= +MI_ExportScenes= +MI_ExposeResource= +MI_FieldGuide="Ctrl+'" +MI_FileInfo= +MI_FillAreas= +MI_FillLines= +MI_FirstFrame=Home +MI_FoldColumns= +MI_FrezzePreview= +MI_GCheck= +MI_GetColorFromStudioPalette= +MI_GreenChannel= +MI_GreenChannelGreyscale= +MI_Histogram= +MI_ICheck= +MI_IOnly= +MI_ImportMagpieFile= +MI_ImportScenes= +MI_IncreaseStep="+" +MI_Increment= +MI_Ink1Check= +MI_InsertGlobalKeyframe= +MI_InsertSceneFrame= +MI_InvertKeyframeSelection= +MI_InvertSelection= +MI_LastFrame=End +MI_LevelSettings= +MI_LinesFade= +MI_Link= +MI_LoadColorModel= +MI_LoadFolder= +MI_LoadLevel= +MI_LoadSubSceneFile= +MI_LockAllColumns= +MI_LockSelectedColumns= +MI_LockThisColumnOnly= +MI_Loop= +MI_MatteChannel= +MI_MergeCmapped= +MI_MergeColumns= +MI_MergeFrames= +MI_NewLevel= +MI_NewOutputFx= +MI_NewProject= +MI_NextStep= +MI_NoShift= +MI_OnionSkin=Ctrl+Alt+O +MI_OpenBatchServers= +MI_OpenChild= +MI_OpenCleanupSettings= +MI_OpenColorModel= +MI_OpenComboViewer= +MI_OpenFileBrowser= +MI_OpenFileBrowser2= +MI_OpenFileViewer= +MI_OpenFilmStrip= +MI_OpenFunctionEditor=Alt+F +MI_OpenHistoryPanel= +MI_OpenLevelView= +MI_OpenPalette= +MI_OpenPltGizmo= +MI_OpenRecentScene= +MI_OpenSchematic= +MI_OpenScriptConsole= +MI_OpenStudioPalette= +MI_OpenStyleControl= +MI_OpenTMessage= +MI_OpenTasks= +MI_OpenToolOptionBar= +MI_OpenToolbar= +MI_OpenXshView= +MI_OutputSettings= +MI_OverwritePalette= +MI_PCheck= +MI_PasteColors= +MI_PasteInto= +MI_PasteNames= +MI_PasteValues= +MI_Pause= +MI_PencilTest= +MI_PickStyleAreas= +MI_PickStyleLines= +MI_Play=Return +MI_Preferences=Ctrl+U +MI_PrevStep= +MI_PreviewFx= +MI_PreviewSettings= +MI_Print= +MI_PrintXsheet= +MI_ProjectSettings= +MI_Random= +MI_RasterizePli= +MI_RedChannel= +MI_RedChannelGreyscale= +MI_Reframe1= +MI_Reframe2= +MI_Reframe3= +MI_Reframe4= +MI_RefreshTree= +MI_RegenerateFramePr= +MI_RegeneratePreview= +MI_ReloadStyle= +MI_RemoveEndpoints= +MI_RemoveGlobalKeyframe= +MI_RemoveLevel= +MI_RemoveSceneFrame= +MI_RemoveUnused= +MI_Render=Ctrl+Alt+Shift+S +MI_Renumber= +MI_ReplaceLevel= +MI_ReplaceParentDirectory= +MI_Resequence= +MI_ResetInterpolation= +MI_ResetRoomLayout= +MI_ResetScanCropbox= +MI_ResetShift= +MI_ResetStep= +MI_Reverse= +MI_RevertScene= +MI_RevertToCleanedUp= +MI_RevertToLastSaved= +MI_Rolldown= +MI_Rollup= +MI_RunScript= +MI_SafeArea= +MI_SaveAll=Ctrl+S +MI_SaveDefaultSettings= +MI_SaveLevel= +MI_SaveLevelAs= +MI_SavePaletteAs= +MI_SavePreset= +MI_SavePreviewedFrames= +MI_SaveSubxsheetAs= +MI_Scan= +MI_ScanSettings= +MI_SceneSettings=Ctrl+F3 +MI_SelectAllKeyframes= +MI_SelectAllKeyframesNotAfter= +MI_SelectAllKeyframesNotBefore= +MI_SelectColumnKeyframes= +MI_SelectFollowingKeysInColumn= +MI_SelectFollowingKeysInRow= +MI_SelectPreviousKeysInColumn= +MI_SelectPreviousKeysInRow= +MI_SelectRowKeyframes= +MI_SetAcceleration= +MI_SetConstantSpeed= +MI_SetDeceleration= +MI_SetKeyframes=Ctrl+F6 +MI_SetScanCropbox= +MI_ShiftTrace= +MI_ShortcutPopup= +MI_ShowFolderContents= +MI_Step2= +MI_Step3= +MI_Step4= +MI_SwapEnabledColumns= +MI_Swing= +MI_TCheck= +MI_TimeStretch= +MI_ToggleColumnLocks= +MI_ToggleColumnsActivation= +MI_ToggleEditInPlace= +MI_Tracking= +MI_Ungroup=Ctrl+Shift+G +MI_UnlockAllColumns=Ctrl+Alt+Shift+L +MI_UnlockSelectedColumns=Ctrl+Shift+K +MI_ViewBBox= +MI_ViewCamera= +MI_ViewColorcard= +MI_ViewFile= +MI_ViewGuide= +MI_ViewRuler=Ctrl+Alt+Shift+R +MI_ViewTable= +T_Bender= +T_Cutter=Alt+T +T_Finger= +T_Hook= +T_Iron= +T_Magnet= +T_PaintBrush= +T_Plastic= +T_Pump= +T_RGBPicker= +T_Ruler= +T_ShowHideFullScreen=F4 +T_Skeleton= +T_Tracker= +T_ZoomFit= +MI_OpenRecentLevel= diff --git a/stuff/profiles/layouts/shortcuts/otharmony.ini b/stuff/profiles/layouts/shortcuts/otharmony.ini new file mode 100644 index 0000000..8464172 --- /dev/null +++ b/stuff/profiles/layouts/shortcuts/otharmony.ini @@ -0,0 +1,366 @@ +[shortcuts] +MI_LoadRecentImage= +A_ToolOption_FrameRange= +A_ToolOption_SegmentInk= +A_ToolOption_Selective= +A_ToolOption_Type%3ARectangular= +MI_BringForward=Ctrl+PgUp +MI_BringToFront=Ctrl+Shift+PgUp +MI_Clear=Delete +MI_Copy=Ctrl+C +MI_Cut=Ctrl+X +MI_DrawingSubBackward=[ +MI_DrawingSubForward=] +MI_DrawingSubGroupBackward=Ctrl+[ +MI_DrawingSubGroupForward=Ctrl+] +MI_Duplicate= +MI_FullScreenWindow=Ctrl+F +MI_FxParamEditor= +MI_Group=Ctrl+G +MI_Insert=Ins +MI_InsertFx= +MI_LoadScene=Ctrl+O +MI_MaximizePanel=` +MI_NewScene=Ctrl+N +MI_NextDrawing=G +MI_NextFrame=. +MI_OpacityCheck= +MI_Paste=Ctrl+V +MI_PrevDrawing=F +MI_PrevFrame="," +MI_Preview= +MI_Quit=Ctrl+Q +MI_Redo=Ctrl+Shift+Z +MI_SaveScene=Ctrl+Shift+S +MI_SaveSceneAs=Ctrl+Shift+Alt+S +MI_SelectAll=Ctrl+A +MI_SendBack=Ctrl+PgDown +MI_SendBackward=Ctrl+Shift+PgDown +MI_Undo=Ctrl+Z +MI_ZeroThick= +T_ActualPixelSize= +T_Brush=Alt+B +T_ControlPointEditor=Alt+Q +T_Edit=Shift+T +T_Eraser=Alt+E +T_Fill=Alt+I +T_Geometric=Alt+7 +T_Hand= +T_Pinch= +T_Rotate= +T_Selection=Alt+S +T_StylePicker=Alt+D +T_Tape=Alt+C +T_Type=Alt+9 +T_Zoom=Alt+Z +T_ZoomReset= +T_Zoomin=2 +T_Zoomout=1 +A_DecreaseBrushHardness= +A_DecreaseMaxBrushThickness= +A_DecreaseMinBrushThickness= +A_FxSchematicToggle= +A_IncreaseBrushHardness= +A_IncreaseMaxBrushThickness= +A_IncreaseMinBrushThickness= +A_ToolOption_AutoGroup= +A_ToolOption_AutoSelect%3AColumn= +A_ToolOption_AutoSelect%3ANone= +A_ToolOption_AutoSelect%3APegbar= +A_ToolOption_AutoSelectDrawing= +A_ToolOption_Autofill= +A_ToolOption_BreakSharpAngles= +A_ToolOption_BrushPreset= +A_ToolOption_EditToolActiveAxis= +A_ToolOption_EditToolActiveAxis%3ACenter= +A_ToolOption_EditToolActiveAxis%3APosition=Alt+2 +A_ToolOption_EditToolActiveAxis%3ARotation=Alt+3 +A_ToolOption_EditToolActiveAxis%3AScale=Alt+4 +A_ToolOption_EditToolActiveAxis%3AShear=Alt+5 +A_ToolOption_GeometricEdge= +A_ToolOption_GeometricShape= +A_ToolOption_GlobalKey= +A_ToolOption_IK= +A_ToolOption_Invert= +A_ToolOption_JoinVectors= +A_ToolOption_Manual= +A_ToolOption_Meshify= +A_ToolOption_Mode= +A_ToolOption_Mode%3AAreas= +A_ToolOption_Mode%3ALines= +A_ToolOption_Mode%3ALines%20%26%20Areas= +A_ToolOption_OnionSkin= +A_ToolOption_Orientation= +A_ToolOption_PencilMode= +A_ToolOption_PickScreen= +A_ToolOption_PreserveThickness= +A_ToolOption_PressureSensitivity= +A_ToolOption_ShowOnlyActiveSkeleton= +A_ToolOption_SkeletonMode%3AAnimate= +A_ToolOption_SkeletonMode%3ABuild%20Skeleton= +A_ToolOption_SkeletonMode%3AInverse%20Kinematics= +A_ToolOption_Smooth= +A_ToolOption_Snap= +A_ToolOption_Type= +A_ToolOption_Type%3AFreehand= +A_ToolOption_Type%3ANormal= +A_ToolOption_Type%3APolyline= +A_ToolOption_TypeFont= +A_ToolOption_TypeSize= +A_ToolOption_TypeStyle= +MI_ACheck= +MI_About= +MI_ActivateAllColumns= +MI_ActivateSelectedColumns= +MI_ActivateThisColumnOnly= +MI_AddFrames= +MI_AddToBatchCleanupList= +MI_AddToBatchRenderList= +MI_AdjustLevels= +MI_AdjustThickness= +MI_Antialias= +MI_ApplyMatchLines= +MI_AutoFillToggle= +MI_Autocenter= +MI_Autorenumber= +MI_BCheck= +MI_Binarize= +MI_BlendColors= +MI_BlueChannel= +MI_BlueChannelGreyscale= +MI_BrightnessAndContrast= +MI_CameraSettings= +MI_CameraStage= +MI_CameraTest= +MI_CanvasSize= +MI_Cleanup= +MI_CleanupPreview= +MI_CleanupSettings= +MI_ClearRecentImage= +MI_ClearRecentLevel= +MI_ClearRecentScene= +MI_CloneChild= +MI_CloneLevel= +MI_ClonePreview= +MI_CloseChild= +MI_Collapse=0 +MI_CollectAssets= +MI_CompareToSnapshot= +MI_ConvertFileWithInput= +MI_ConvertFiles= +MI_ConvertToVectors= +MI_DeactivateAllColumns= +MI_DeactivateSelectedColumns= +MI_DeactivateUpperColumns= +MI_DecreaseStep=- +MI_DefineScanner= +MI_DeleteInk= +MI_DeleteMatchLines= +MI_DisableAllColumns= +MI_DisableSelectedColumns=Alt+H +MI_DockingCheck= +MI_Dup= +MI_DuplicateFile= +MI_Each2= +MI_Each3= +MI_Each4= +MI_EditLevel= +MI_EditShift= +MI_EnableAllColumns=Alt+Shift+H +MI_EnableSelectedColumns= +MI_EnableThisColumnOnly= +MI_EnterGroup=Ctrl+Return +MI_EraseUnusedStyles= +MI_ExitGroup=Backspace +MI_ExplodeChild=Ctrl+B +MI_ExportLevel= +MI_ExportScenes= +MI_ExposeResource= +MI_FieldGuide="Ctrl+'" +MI_FileInfo= +MI_FillAreas= +MI_FillLines= +MI_FirstFrame="Shift+<" +MI_FoldColumns= +MI_FrezzePreview= +MI_GCheck= +MI_GetColorFromStudioPalette= +MI_GreenChannel= +MI_GreenChannelGreyscale= +MI_Histogram= +MI_ICheck= +MI_IOnly= +MI_ImportMagpieFile= +MI_ImportScenes= +MI_IncreaseStep="+" +MI_Increment= +MI_Ink1Check= +MI_InsertGlobalKeyframe= +MI_InsertSceneFrame= +MI_InvertKeyframeSelection= +MI_InvertSelection= +MI_LastFrame="Shift+>" +MI_LevelSettings= +MI_LinesFade= +MI_Link= +MI_LoadColorModel= +MI_LoadFolder= +MI_LoadLevel= +MI_LoadSubSceneFile= +MI_LockAllColumns=Ctrl+Shift+L +MI_LockSelectedColumns=Ctrl+Alt+L +MI_LockThisColumnOnly= +MI_Loop= +MI_MatteChannel= +MI_MergeCmapped= +MI_MergeColumns= +MI_MergeFrames= +MI_NewLevel= +MI_NewOutputFx= +MI_NewProject= +MI_NextStep= +MI_NoShift= +MI_OnionSkin=Alt+O +MI_OpenBatchServers= +MI_OpenChild= +MI_OpenCleanupSettings= +MI_OpenColorModel= +MI_OpenComboViewer= +MI_OpenFileBrowser= +MI_OpenFileBrowser2= +MI_OpenFileViewer= +MI_OpenFilmStrip= +MI_OpenFunctionEditor=Alt+F +MI_OpenHistoryPanel= +MI_OpenLevelView= +MI_OpenPalette= +MI_OpenPltGizmo= +MI_OpenRecentScene= +MI_OpenSchematic= +MI_OpenScriptConsole= +MI_OpenStudioPalette= +MI_OpenStyleControl= +MI_OpenTMessage= +MI_OpenTasks= +MI_OpenToolOptionBar= +MI_OpenToolbar= +MI_OpenXshView= +MI_OutputSettings= +MI_OverwritePalette= +MI_PCheck= +MI_PasteColors= +MI_PasteInto= +MI_PasteNames= +MI_PasteValues= +MI_Pause= +MI_PencilTest= +MI_PickStyleAreas= +MI_PickStyleLines= +MI_Play=Ctrl+Return +MI_Preferences=Ctrl+U +MI_PrevStep= +MI_PreviewFx= +MI_PreviewSettings= +MI_Print= +MI_PrintXsheet= +MI_ProjectSettings= +MI_Random= +MI_RasterizePli= +MI_RedChannel= +MI_RedChannelGreyscale= +MI_Reframe1= +MI_Reframe2= +MI_Reframe3= +MI_Reframe4= +MI_RefreshTree= +MI_RegenerateFramePr= +MI_RegeneratePreview= +MI_ReloadStyle= +MI_RemoveEndpoints= +MI_RemoveGlobalKeyframe= +MI_RemoveLevel= +MI_RemoveSceneFrame= +MI_RemoveUnused= +MI_Render= +MI_Renumber= +MI_ReplaceLevel= +MI_ReplaceParentDirectory= +MI_Resequence= +MI_ResetInterpolation= +MI_ResetRoomLayout= +MI_ResetScanCropbox= +MI_ResetShift= +MI_ResetStep= +MI_Reverse= +MI_RevertScene= +MI_RevertToCleanedUp= +MI_RevertToLastSaved= +MI_Rolldown= +MI_Rollup= +MI_RunScript= +MI_SafeArea= +MI_SaveAll=Ctrl+S +MI_SaveDefaultSettings= +MI_SaveLevel= +MI_SaveLevelAs= +MI_SavePaletteAs= +MI_SavePreset= +MI_SavePreviewedFrames= +MI_SaveSubxsheetAs= +MI_Scan=Ctrl+Shift+S +MI_ScanSettings= +MI_SceneSettings= +MI_SelectAllKeyframes= +MI_SelectAllKeyframesNotAfter= +MI_SelectAllKeyframesNotBefore= +MI_SelectColumnKeyframes= +MI_SelectFollowingKeysInColumn= +MI_SelectFollowingKeysInRow= +MI_SelectPreviousKeysInColumn= +MI_SelectPreviousKeysInRow= +MI_SelectRowKeyframes= +MI_SetAcceleration= +MI_SetConstantSpeed= +MI_SetDeceleration= +MI_SetKeyframes=F6 +MI_SetScanCropbox= +MI_ShiftTrace= +MI_ShortcutPopup= +MI_ShowFolderContents= +MI_Step2= +MI_Step3= +MI_Step4= +MI_SwapEnabledColumns= +MI_Swing= +MI_TCheck= +MI_TimeStretch= +MI_ToggleColumnLocks= +MI_ToggleColumnsActivation= +MI_ToggleEditInPlace= +MI_Tracking= +MI_Ungroup=Ctrl+Shift+G +MI_UnlockAllColumns=Ctrl+Alt+Shift+K +MI_UnlockSelectedColumns=Ctrl+Shift+K +MI_ViewBBox= +MI_ViewCamera= +MI_ViewColorcard= +MI_ViewFile= +MI_ViewGuide="Ctrl+'" +MI_ViewRuler= +MI_ViewTable= +T_Bender= +T_Cutter=Alt+T +T_Finger= +T_Hook= +T_Iron= +T_Magnet= +T_PaintBrush= +T_Plastic= +T_Pump= +T_RGBPicker= +T_Ruler= +T_ShowHideFullScreen= +T_Skeleton= +T_Tracker= +T_ZoomFit= +MI_OpenRecentLevel= diff --git a/stuff/profiles/layouts/shortcuts/otretas.ini b/stuff/profiles/layouts/shortcuts/otretas.ini new file mode 100644 index 0000000..7a1b172 --- /dev/null +++ b/stuff/profiles/layouts/shortcuts/otretas.ini @@ -0,0 +1,366 @@ +[shortcuts] +MI_LoadRecentImage= +A_ToolOption_FrameRange= +A_ToolOption_SegmentInk= +A_ToolOption_Selective= +A_ToolOption_Type%3ARectangular= +MI_BringForward=Ctrl+Up +MI_BringToFront=Ctrl+Shift+Up +MI_Clear=Delete +MI_Copy=Ctrl+C +MI_Cut=Ctrl+X +MI_DrawingSubBackward=[ +MI_DrawingSubForward=] +MI_DrawingSubGroupBackward=Ctrl+[ +MI_DrawingSubGroupForward=Ctrl+] +MI_Duplicate= +MI_FullScreenWindow=Ctrl+F +MI_FxParamEditor= +MI_Group=Ctrl+G +MI_Insert=Ins +MI_InsertFx= +MI_LoadScene=Ctrl+O +MI_MaximizePanel= +MI_NewScene=Ctrl+N +MI_NextDrawing=G +MI_NextFrame=. +MI_OpacityCheck= +MI_Paste=Ctrl+V +MI_PrevDrawing=F +MI_PrevFrame="," +MI_Preview=Alt+P +MI_Quit=Ctrl+Q +MI_Redo=Ctrl+Y +MI_SaveScene=Ctrl+Shift+S +MI_SaveSceneAs=Ctrl+Alt+Shift+S +MI_SelectAll=Shift+A +MI_SendBack=Ctrl+Shift+Down +MI_SendBackward=Ctrl+Down +MI_Undo=Ctrl+Z +MI_ZeroThick=D +T_ActualPixelSize= +T_Brush=Alt+B +T_ControlPointEditor=Alt+A +T_Edit=Alt+Q +T_Eraser=Alt+E +T_Fill=Alt+K +T_Geometric=Atl+R +T_Hand= +T_Pinch= +T_Rotate= +T_Selection=Alt+V +T_StylePicker=Alt+I +T_Tape=Alt+C +T_Type= +T_Zoom=Alt+Z +T_ZoomReset=Shift+Z +T_Zoomin=Ctrl+= +T_Zoomout=Ctrl+- +A_DecreaseBrushHardness= +A_DecreaseMaxBrushThickness= +A_DecreaseMinBrushThickness= +A_FxSchematicToggle= +A_IncreaseBrushHardness= +A_IncreaseMaxBrushThickness= +A_IncreaseMinBrushThickness= +A_ToolOption_AutoGroup= +A_ToolOption_AutoSelect%3AColumn= +A_ToolOption_AutoSelect%3ANone= +A_ToolOption_AutoSelect%3APegbar= +A_ToolOption_AutoSelectDrawing= +A_ToolOption_Autofill= +A_ToolOption_BreakSharpAngles= +A_ToolOption_BrushPreset= +A_ToolOption_EditToolActiveAxis= +A_ToolOption_EditToolActiveAxis%3ACenter= +A_ToolOption_EditToolActiveAxis%3APosition= +A_ToolOption_EditToolActiveAxis%3ARotation= +A_ToolOption_EditToolActiveAxis%3AScale= +A_ToolOption_EditToolActiveAxis%3AShear= +A_ToolOption_GeometricEdge= +A_ToolOption_GeometricShape= +A_ToolOption_GlobalKey= +A_ToolOption_IK=Alt+8 +A_ToolOption_Invert= +A_ToolOption_JoinVectors= +A_ToolOption_Manual= +A_ToolOption_Meshify= +A_ToolOption_Mode= +A_ToolOption_Mode%3AAreas= +A_ToolOption_Mode%3ALines= +A_ToolOption_Mode%3ALines%20%26%20Areas= +A_ToolOption_OnionSkin= +A_ToolOption_Orientation= +A_ToolOption_PencilMode= +A_ToolOption_PickScreen= +A_ToolOption_PreserveThickness= +A_ToolOption_PressureSensitivity= +A_ToolOption_ShowOnlyActiveSkeleton= +A_ToolOption_SkeletonMode%3AAnimate= +A_ToolOption_SkeletonMode%3ABuild%20Skeleton= +A_ToolOption_SkeletonMode%3AInverse%20Kinematics= +A_ToolOption_Smooth= +A_ToolOption_Snap= +A_ToolOption_Type= +A_ToolOption_Type%3AFreehand= +A_ToolOption_Type%3ANormal= +A_ToolOption_Type%3APolyline= +A_ToolOption_TypeFont= +A_ToolOption_TypeSize= +A_ToolOption_TypeStyle= +MI_ACheck= +MI_About= +MI_ActivateAllColumns= +MI_ActivateSelectedColumns= +MI_ActivateThisColumnOnly= +MI_AddFrames=Ctrl+H +MI_AddToBatchCleanupList= +MI_AddToBatchRenderList= +MI_AdjustLevels= +MI_AdjustThickness= +MI_Antialias= +MI_ApplyMatchLines= +MI_AutoFillToggle= +MI_Autocenter= +MI_Autorenumber= +MI_BCheck= +MI_Binarize= +MI_BlendColors= +MI_BlueChannel= +MI_BlueChannelGreyscale= +MI_BrightnessAndContrast= +MI_CameraSettings= +MI_CameraStage= +MI_CameraTest= +MI_CanvasSize= +MI_Cleanup= +MI_CleanupPreview= +MI_CleanupSettings= +MI_ClearRecentImage= +MI_ClearRecentLevel= +MI_ClearRecentScene= +MI_CloneChild= +MI_CloneLevel= +MI_ClonePreview= +MI_CloseChild= +MI_Collapse= +MI_CollectAssets= +MI_CompareToSnapshot= +MI_ConvertFileWithInput= +MI_ConvertFiles= +MI_ConvertToVectors= +MI_DeactivateAllColumns= +MI_DeactivateSelectedColumns=Alt+H +MI_DeactivateUpperColumns= +MI_DecreaseStep= +MI_DefineScanner= +MI_DeleteInk= +MI_DeleteMatchLines= +MI_DisableAllColumns= +MI_DisableSelectedColumns= +MI_DockingCheck= +MI_Dup= +MI_DuplicateFile= +MI_Each2= +MI_Each3= +MI_Each4= +MI_EditLevel= +MI_EditShift= +MI_EnableAllColumns=Alt+Shift+H +MI_EnableSelectedColumns= +MI_EnableThisColumnOnly= +MI_EnterGroup=Ctrl+Return +MI_EraseUnusedStyles= +MI_ExitGroup=Backspace +MI_ExplodeChild=Ctrl+B +MI_ExportLevel= +MI_ExportScenes= +MI_ExposeResource= +MI_FieldGuide="Ctrl+'" +MI_FileInfo= +MI_FillAreas= +MI_FillLines= +MI_FirstFrame=Home +MI_FoldColumns= +MI_FrezzePreview= +MI_GCheck= +MI_GetColorFromStudioPalette= +MI_GreenChannel= +MI_GreenChannelGreyscale= +MI_Histogram= +MI_ICheck= +MI_IOnly= +MI_ImportMagpieFile= +MI_ImportScenes= +MI_IncreaseStep="+" +MI_Increment= +MI_Ink1Check= +MI_InsertGlobalKeyframe= +MI_InsertSceneFrame= +MI_InvertKeyframeSelection= +MI_InvertSelection= +MI_LastFrame=End +MI_LevelSettings= +MI_LinesFade= +MI_Link= +MI_LoadColorModel= +MI_LoadFolder= +MI_LoadLevel= +MI_LoadSubSceneFile= +MI_LockAllColumns= +MI_LockSelectedColumns= +MI_LockThisColumnOnly= +MI_Loop= +MI_MatteChannel= +MI_MergeCmapped= +MI_MergeColumns= +MI_MergeFrames= +MI_NewLevel= +MI_NewOutputFx= +MI_NewProject= +MI_NextStep= +MI_NoShift= +MI_OnionSkin=Ctrl+Alt+O +MI_OpenBatchServers= +MI_OpenChild= +MI_OpenCleanupSettings= +MI_OpenColorModel= +MI_OpenComboViewer= +MI_OpenFileBrowser= +MI_OpenFileBrowser2= +MI_OpenFileViewer= +MI_OpenFilmStrip= +MI_OpenFunctionEditor=Alt+F +MI_OpenHistoryPanel= +MI_OpenLevelView= +MI_OpenPalette= +MI_OpenPltGizmo= +MI_OpenRecentScene= +MI_OpenSchematic= +MI_OpenScriptConsole= +MI_OpenStudioPalette= +MI_OpenStyleControl= +MI_OpenTMessage= +MI_OpenTasks= +MI_OpenToolOptionBar= +MI_OpenToolbar= +MI_OpenXshView= +MI_OutputSettings= +MI_OverwritePalette= +MI_PCheck= +MI_PasteColors= +MI_PasteInto= +MI_PasteNames= +MI_PasteValues= +MI_Pause= +MI_PencilTest= +MI_PickStyleAreas= +MI_PickStyleLines= +MI_Play=Return +MI_Preferences=Ctrl+U +MI_PrevStep= +MI_PreviewFx= +MI_PreviewSettings= +MI_Print= +MI_PrintXsheet= +MI_ProjectSettings= +MI_Random= +MI_RasterizePli= +MI_RedChannel= +MI_RedChannelGreyscale= +MI_Reframe1= +MI_Reframe2= +MI_Reframe3= +MI_Reframe4= +MI_RefreshTree= +MI_RegenerateFramePr= +MI_RegeneratePreview= +MI_ReloadStyle= +MI_RemoveEndpoints= +MI_RemoveGlobalKeyframe= +MI_RemoveLevel= +MI_RemoveSceneFrame= +MI_RemoveUnused= +MI_Render=Ctrl+Alt+Shift+S +MI_Renumber= +MI_ReplaceLevel= +MI_ReplaceParentDirectory= +MI_Resequence= +MI_ResetInterpolation= +MI_ResetRoomLayout= +MI_ResetScanCropbox= +MI_ResetShift= +MI_ResetStep= +MI_Reverse= +MI_RevertScene= +MI_RevertToCleanedUp= +MI_RevertToLastSaved= +MI_Rolldown= +MI_Rollup= +MI_RunScript= +MI_SafeArea= +MI_SaveAll=Ctrl+S +MI_SaveDefaultSettings= +MI_SaveLevel= +MI_SaveLevelAs= +MI_SavePaletteAs= +MI_SavePreset= +MI_SavePreviewedFrames= +MI_SaveSubxsheetAs= +MI_Scan= +MI_ScanSettings= +MI_SceneSettings=Ctrl+F3 +MI_SelectAllKeyframes= +MI_SelectAllKeyframesNotAfter= +MI_SelectAllKeyframesNotBefore= +MI_SelectColumnKeyframes= +MI_SelectFollowingKeysInColumn= +MI_SelectFollowingKeysInRow= +MI_SelectPreviousKeysInColumn= +MI_SelectPreviousKeysInRow= +MI_SelectRowKeyframes= +MI_SetAcceleration= +MI_SetConstantSpeed= +MI_SetDeceleration= +MI_SetKeyframes=Ctrl+F6 +MI_SetScanCropbox= +MI_ShiftTrace= +MI_ShortcutPopup= +MI_ShowFolderContents= +MI_Step2= +MI_Step3= +MI_Step4= +MI_SwapEnabledColumns= +MI_Swing= +MI_TCheck= +MI_TimeStretch= +MI_ToggleColumnLocks= +MI_ToggleColumnsActivation= +MI_ToggleEditInPlace= +MI_Tracking= +MI_Ungroup=Ctrl+Shift+G +MI_UnlockAllColumns=Ctrl+Alt+Shift+L +MI_UnlockSelectedColumns=Ctrl+Shift+K +MI_ViewBBox= +MI_ViewCamera= +MI_ViewColorcard= +MI_ViewFile= +MI_ViewGuide= +MI_ViewRuler=Ctrl+Alt+Shift+R +MI_ViewTable= +T_Bender= +T_Cutter=Alt+T +T_Finger= +T_Hook= +T_Iron= +T_Magnet= +T_PaintBrush= +T_Plastic= +T_Pump= +T_RGBPicker= +T_Ruler= +T_ShowHideFullScreen=F4 +T_Skeleton= +T_Tracker= +T_ZoomFit= +MI_OpenRecentLevel= diff --git a/thirdparty/libpng-1.6.21/lib/libpng16_2015.lib b/thirdparty/libpng-1.6.21/lib/libpng16_2015.lib index ca4827f..1e7bbcf 100644 --- a/thirdparty/libpng-1.6.21/lib/libpng16_2015.lib +++ b/thirdparty/libpng-1.6.21/lib/libpng16_2015.lib @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d6be973caafd36b6dcf9b8fcb2d030ad2e0c3c523527fad7bbf7da9f9ba5b6e -size 56118 +oid sha256:e005a1c28ab5a1f8ed57793a79c883f0b44cd5d2b25152544e3dca5fbdd616bc +size 374568 diff --git a/thirdparty/libpng-1.6.21/lib/libpng16_2015d.lib b/thirdparty/libpng-1.6.21/lib/libpng16_2015d.lib index a94d492..1859771 100644 --- a/thirdparty/libpng-1.6.21/lib/libpng16_2015d.lib +++ b/thirdparty/libpng-1.6.21/lib/libpng16_2015d.lib @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be7784d0f86cf87b9dd965a32707e1a999b059d57fbeddb4066a033200e0fbc9 -size 56118 +oid sha256:f61acffbae2925d60a61bd11b6d5b09502843c89c8b3f20b89f240e050a1e916 +size 858596 diff --git a/thirdparty/tiff-4.0.3/libtiff/tif_config.vc.h b/thirdparty/tiff-4.0.3/libtiff/tif_config.vc.h index c297cf3..859a606 100644 --- a/thirdparty/tiff-4.0.3/libtiff/tif_config.vc.h +++ b/thirdparty/tiff-4.0.3/libtiff/tif_config.vc.h @@ -47,7 +47,9 @@ /* Set the native cpu bit order */ #define HOST_FILLORDER FILLORDER_LSB2MSB +#if defined(_MSC_VER) && (_MSC_VER < 1900) #define snprintf _snprintf +#endif /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ diff --git a/toonz/sources/common/tapptools/tcolorutils.cpp b/toonz/sources/common/tapptools/tcolorutils.cpp index 8203a5c..2a620a1 100644 --- a/toonz/sources/common/tapptools/tcolorutils.cpp +++ b/toonz/sources/common/tapptools/tcolorutils.cpp @@ -182,7 +182,8 @@ void chooseLeafToClusterize(ClusterContainer::iterator &itRet, const KEYER_FLOAT *clusterCovariance = cluster->statistic.covariance; assert(!ISNAN(clusterCovariance[0])); - // Calculate the eigenvalues ​​of the covariance matrix of the cluster statistics + // Calculate the eigenvalues ​​of the covariance matrix of the cluster + // statistics // (because the array is symmetrical the eigenvalues are all real) KEYER_FLOAT eigenValues[3]; tmpMulteplicity = calcCovarianceEigenValues(clusterCovariance, eigenValues); diff --git a/toonz/sources/common/tgeometry/tcurveutil.cpp b/toonz/sources/common/tgeometry/tcurveutil.cpp index 87140c3..ff0c3b4 100644 --- a/toonz/sources/common/tgeometry/tcurveutil.cpp +++ b/toonz/sources/common/tgeometry/tcurveutil.cpp @@ -284,7 +284,8 @@ int intersect(const TQuadratic &c0, const TQuadratic &c1, // This function checks whether the control point // p1 is very close to p0 or p2. // In this case, we are approximated to the quadratic p0-p2 segment. -// If p1 is near p0, the relationship between the original and the quadratic segment: +// If p1 is near p0, the relationship between the original and the quadratic +// segment: // tq = sqrt(ts), // If p1 is near p2, instead it's: // tq = 1-sqrt(1-ts). diff --git a/toonz/sources/common/tsystem/tfilepath.cpp b/toonz/sources/common/tsystem/tfilepath.cpp index 215a042..d16a1a3 100644 --- a/toonz/sources/common/tsystem/tfilepath.cpp +++ b/toonz/sources/common/tsystem/tfilepath.cpp @@ -480,6 +480,7 @@ bool TFilePath::isRoot() const { // ritorna ""(niente tipo, niente punto), "." (file con tipo) o ".." (file con // tipo e frame) std::string TFilePath::getDots() const { + if (isFfmpegType()) return "."; int i = getLastSlash(m_path); std::wstring str = m_path.substr(i + 1); // potrei anche avere a.b.c.d dove d e' l'estensione @@ -561,7 +562,7 @@ std::string TFilePath::getLevelName() const { std::wstring TFilePath::getLevelNameW() const { int i = getLastSlash(m_path); // cerco l'ultimo slash std::wstring str = m_path.substr(i + 1); // str e' m_path senza directory - + if (isFfmpegType()) return str; int j = str.rfind(L"."); // str[j..] = ".type" if (j == (int)std::wstring::npos) return str; // no frame; no type i = str.substr(0, j).rfind(L'.'); @@ -597,6 +598,7 @@ TFilePath TFilePath::getParentDir() const // noSlash! //----------------------------------------------------------------------------- bool TFilePath::isLevelName() const { + if (isFfmpegType()) return false; try { return getFrame() == TFrameId(TFrameId::EMPTY_FRAME); } @@ -638,6 +640,15 @@ TFrameId TFilePath::getFrame() const { //----------------------------------------------------------------------------- +bool TFilePath::isFfmpegType() const { + QString type = QString::fromStdString(getType()).toLower(); + if (type == "gif" || type == "mp4" || type == "webm") + return true; + else + return false; +} + +//----------------------------------------------------------------------------- TFilePath TFilePath::withType(const std::string &type) const { assert(type.length() < 2 || type.substr(0, 2) != ".."); int i = getLastSlash(m_path); // cerco l'ultimo slash diff --git a/toonz/sources/common/tvrender/tcolorstyles.cpp b/toonz/sources/common/tvrender/tcolorstyles.cpp index 3b18ce5..a67f8f1 100644 --- a/toonz/sources/common/tvrender/tcolorstyles.cpp +++ b/toonz/sources/common/tvrender/tcolorstyles.cpp @@ -50,7 +50,8 @@ TColorStyle::TColorStyle() , m_enabled(true) , m_icon(0) , m_validIcon(false) - , m_isEditedFromOriginal(false) {} + , m_isEditedFromOriginal(false) + , m_pickedPosition() {} //------------------------------------------------------------------- @@ -66,7 +67,8 @@ TColorStyle::TColorStyle(const TColorStyle &other) , m_flags(other.m_flags) , m_enabled(other.m_enabled) , m_validIcon(false) - , m_isEditedFromOriginal(other.m_isEditedFromOriginal) {} + , m_isEditedFromOriginal(other.m_isEditedFromOriginal) + , m_pickedPosition(other.m_pickedPosition) {} //------------------------------------------------------------------- @@ -79,6 +81,7 @@ TColorStyle &TColorStyle::operator=(const TColorStyle &other) { m_enabled = other.m_enabled; m_validIcon = false; m_isEditedFromOriginal = other.m_isEditedFromOriginal; + m_pickedPosition = other.m_pickedPosition; return *this; } @@ -100,6 +103,7 @@ bool TColorStyle::operator==(const TColorStyle &cs) const { if (m_originalName != cs.getOriginalName()) return false; if (m_globalName != cs.getGlobalName()) return false; if (m_isEditedFromOriginal != cs.getIsEditedFlag()) return false; + if (m_pickedPosition != cs.getPickedPosition()) return false; for (int p = 0; p < colorParamCount; ++p) if (getColorParamValue(p) != cs.getColorParamValue(p)) return false; diff --git a/toonz/sources/common/tvrender/tpalette.cpp b/toonz/sources/common/tvrender/tpalette.cpp index f3e229e..ad236ef 100644 --- a/toonz/sources/common/tvrender/tpalette.cpp +++ b/toonz/sources/common/tvrender/tpalette.cpp @@ -15,6 +15,7 @@ #include "tpalette.h" #include +#include PERSIST_IDENTIFIER(TPalette, "palette") @@ -30,6 +31,21 @@ namespace { const int maxStyleIndex = 32765; +const std::string pointToString(const TPoint &point) { + return std::to_string(point.x) + "," + std::to_string(point.y); +} + +// splitting string with ',' +const TPoint stringToPoint(const std::string &string) { + std::string buffer; + std::stringstream ss(string); + std::getline(ss, buffer, ','); // getting the first part of string + int x = std::stoi(buffer); + std::getline(ss, buffer); // getting the second part of string + int y = std::stoi(buffer); + return TPoint(x, y); +} + } // namespace //=================================================================== @@ -564,10 +580,17 @@ void TPalette::saveData(TOStream &os) { os.openChild("styles"); { for (int i = 0; i < getStyleCount(); ++i) { - os.openChild("style"); + TColorStyleP style = m_styles[i].second; + if (style->getPickedPosition() == TPoint()) + os.openChild("style"); + else { + std::map attr; + attr["pickedpos"] = pointToString(style->getPickedPosition()); + os.openChild("style", attr); + } { StyleWriter w(os, i); - m_styles[i].second->save(w); + style->save(w); } os.closeChild(); } @@ -681,6 +704,10 @@ void TPalette::loadData(TIStream &is) { StyleReader r(is, version); TColorStyle *cs = TColorStyle::load(r); + std::string pickedPosStr; + if (is.getTagParam("pickedpos", pickedPosStr)) + cs->setPickedPosition(stringToPoint(pickedPosStr)); + addStyle(cs); } @@ -1096,6 +1123,18 @@ void TPalette::setShortcutValue(int key, int styleId) { } //------------------------------------------------------------------- +// Returns true if there is at least one style with picked pos value +//------------------------------------------------------------------- + +bool TPalette::hasPickedPosStyle() { + for (int i = 0; i < getStyleCount(); ++i) { + TColorStyleP style = m_styles[i].second; + if (style->getPickedPosition() != TPoint()) return true; + } + return false; +} + +//------------------------------------------------------------------- void TPalette::nextShortcutScope(bool invert) { if (invert) { diff --git a/toonz/sources/image/CMakeLists.txt b/toonz/sources/image/CMakeLists.txt index d0a19c2..b610a1d 100644 --- a/toonz/sources/image/CMakeLists.txt +++ b/toonz/sources/image/CMakeLists.txt @@ -69,7 +69,7 @@ if(WIN32) mov/tiio_movW.cpp 3gp/tiio_3gpW.cpp ) -else() +elseif(APPLE) set(HEADERS ${HEADERS} mov/tiio_movM.h 3gp/tiio_3gpM.h diff --git a/toonz/sources/image/ffmpeg/tiio_ffmpeg.cpp b/toonz/sources/image/ffmpeg/tiio_ffmpeg.cpp index 3f35abe..9dd86a1 100644 --- a/toonz/sources/image/ffmpeg/tiio_ffmpeg.cpp +++ b/toonz/sources/image/ffmpeg/tiio_ffmpeg.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "toonz/preferences.h" #include "toonz/toonzfolders.h" @@ -98,8 +99,9 @@ void Ffmpeg::setFrameRate(double fps) { m_frameRate = fps; } void Ffmpeg::setPath(TFilePath path) { m_path = path; } void Ffmpeg::createIntermediateImage(const TImageP &img, int frameIndex) { + m_frameCount++; QString tempPath = m_path.getQString() + "tempOut" + - QString::number(frameIndex) + "." + m_intermediateFormat; + QString::number(m_frameCount) + "." + m_intermediateFormat; std::string saveStatus = ""; TRasterImageP tempImage(img); TRasterImage *image = (TRasterImage *)tempImage->cloneImage(); @@ -127,7 +129,7 @@ void Ffmpeg::createIntermediateImage(const TImageP &img, int frameIndex) { qi->save(tempPath, format, -1); free(buffer); m_cleanUpList.push_back(tempPath); - m_frameCount++; + delete qi; delete image; } @@ -217,9 +219,9 @@ void Ffmpeg::saveSoundTrack(TSoundTrack *st) { bool Ffmpeg::checkFilesExist() { QString ffmpegCachePath = getFfmpegCache().getQString(); QString tempPath = ffmpegCachePath + "//" + - QString::fromStdString(m_path.getName()) + - QString::fromStdString(m_path.getType()) + "In0001." + - m_intermediateFormat; + m_path.getQString().remove(QRegExp(QString::fromUtf8( + "[-`~!@#$%^&*()_�+=|:;<>��,.?/{}\'\"\\[\\]\\\\]"))) + + "In0001." + m_intermediateFormat; if (TSystem::doesExistFileOrLevel(TFilePath(tempPath))) { return true; } else @@ -229,8 +231,9 @@ bool Ffmpeg::checkFilesExist() { ffmpegFileInfo Ffmpeg::getInfo() { QString ffmpegCachePath = getFfmpegCache().getQString(); QString tempPath = ffmpegCachePath + "//" + - QString::fromStdString(m_path.getName()) + - QString::fromStdString(m_path.getType()) + ".txt"; + m_path.getQString().remove(QRegExp(QString::fromUtf8( + "[-`~!@#$%^&*()_�+=|:;<>��,.?/{}\'\"\\[\\]\\\\]"))) + + ".txt"; if (QFile::exists(tempPath)) { QFile infoText(tempPath); infoText.open(QIODevice::ReadOnly); @@ -264,8 +267,8 @@ ffmpegFileInfo Ffmpeg::getInfo() { TRasterImageP Ffmpeg::getImage(int frameIndex) { QString ffmpegCachePath = getFfmpegCache().getQString(); QString tempPath = ffmpegCachePath + "//" + - QString::fromStdString(m_path.getName()) + - QString::fromStdString(m_path.getType()); + m_path.getQString().remove(QRegExp(QString::fromUtf8( + "[-`~!@#$%^&*()_�+=|:;<>��,.?/{}\'\"\\[\\]\\\\]"))); std::string tmpPath = tempPath.toStdString(); // QString tempPath= m_path.getQString(); QString number = QString("%1").arg(frameIndex, 4, 10, QChar('0')); @@ -356,8 +359,8 @@ int Ffmpeg::getFrameCount() { void Ffmpeg::getFramesFromMovie(int frame) { QString ffmpegCachePath = getFfmpegCache().getQString(); QString tempPath = ffmpegCachePath + "//" + - QString::fromStdString(m_path.getName()) + - QString::fromStdString(m_path.getType()); + m_path.getQString().remove(QRegExp(QString::fromUtf8( + "[-`~!@#$%^&*()_�+=|:;<>��,.?/{}\'\"\\[\\]\\\\]"))); std::string tmpPath = tempPath.toStdString(); QString tempName = "In%04d." + m_intermediateFormat; tempName = tempPath + tempName; @@ -399,6 +402,26 @@ void Ffmpeg::getFramesFromMovie(int frame) { } } +int Ffmpeg::getGifFrameCount() { + int frame = 1; + QString ffmpegCachePath = getFfmpegCache().getQString(); + QString tempPath = ffmpegCachePath + "//" + + QString::fromStdString(m_path.getName()) + + QString::fromStdString(m_path.getType()); + std::string tmpPath = tempPath.toStdString(); + QString tempName = "In%04d." + m_intermediateFormat; + tempName = tempPath + tempName; + QString tempStart; + tempStart = "In0001." + m_intermediateFormat; + tempStart = tempPath + tempStart; + while (TSystem::doesExistFileOrLevel(TFilePath(tempStart))) { + frame++; + QString number = QString("%1").arg(frame, 4, 10, QChar('0')); + tempStart = tempPath + "In" + number + "." + m_intermediateFormat; + } + return frame - 1; +} + void Ffmpeg::addToCleanUp(QString path) { if (TSystem::doesExistFileOrLevel(TFilePath(path))) { m_cleanUpList.push_back(path); diff --git a/toonz/sources/image/ffmpeg/tiio_ffmpeg.h b/toonz/sources/image/ffmpeg/tiio_ffmpeg.h index 4b3fe4f..853110a 100644 --- a/toonz/sources/image/ffmpeg/tiio_ffmpeg.h +++ b/toonz/sources/image/ffmpeg/tiio_ffmpeg.h @@ -41,6 +41,7 @@ public: TFilePath getFfmpegCache(); ffmpegFileInfo getInfo(); void disablePrecompute(); + int getGifFrameCount(); private: QString m_intermediateFormat, m_ffmpegPath, m_audioPath, m_audioFormat; diff --git a/toonz/sources/image/ffmpeg/tiio_gif.cpp b/toonz/sources/image/ffmpeg/tiio_gif.cpp index 089461d..0676b91 100644 --- a/toonz/sources/image/ffmpeg/tiio_gif.cpp +++ b/toonz/sources/image/ffmpeg/tiio_gif.cpp @@ -3,6 +3,7 @@ #include "tiio_gif.h" #include "trasterimage.h" #include "timageinfo.h" +#include "toonz/stage.h" #include //=========================================================== @@ -151,8 +152,9 @@ class TImageReaderGif final : public TImageReader { public: int m_frameIndex; - TImageReaderGif(const TFilePath &path, int index, TLevelReaderGif *lra) - : TImageReader(path), m_lra(lra), m_frameIndex(index) { + TImageReaderGif(const TFilePath &path, int index, TLevelReaderGif *lra, + TImageInfo *info) + : TImageReader(path), m_lra(lra), m_frameIndex(index), m_info(info) { m_lra->addRef(); } ~TImageReaderGif() { m_lra->release(); } @@ -160,9 +162,11 @@ public: TImageP load() override { return m_lra->load(m_frameIndex); } TDimension getSize() const { return m_lra->getSize(); } TRect getBBox() const { return TRect(); } + const TImageInfo *getImageInfo() const override { return m_info; } private: TLevelReaderGif *m_lra; + TImageInfo *m_info; // not implemented TImageReaderGif(const TImageReaderGif &); @@ -190,7 +194,7 @@ TLevelReaderGif::TLevelReaderGif(const TFilePath &path) m_ly = m_size.ly; ffmpegReader->getFramesFromMovie(); - + m_frameCount = ffmpegReader->getGifFrameCount(); // set values m_info = new TImageInfo(); m_info->m_frameRate = fps; @@ -198,6 +202,8 @@ TLevelReaderGif::TLevelReaderGif(const TFilePath &path) m_info->m_ly = m_ly; m_info->m_bitsPerSample = 8; m_info->m_samplePerPixel = 4; + m_info->m_dpix = Stage::standardDpi; + m_info->m_dpiy = Stage::standardDpi; } //----------------------------------------------------------- @@ -220,9 +226,8 @@ TImageReaderP TLevelReaderGif::getFrameReader(TFrameId fid) { // if (IOError != 0) // throw TImageException(m_path, buildAVIExceptionString(IOError)); if (fid.getLetter() != 0) return TImageReaderP(0); - int index = fid.getNumber(); - - TImageReaderGif *irm = new TImageReaderGif(m_path, index, this); + int index = fid.getNumber(); + TImageReaderGif *irm = new TImageReaderGif(m_path, index, this, m_info); return TImageReaderP(irm); } diff --git a/toonz/sources/image/ffmpeg/tiio_mp4.cpp b/toonz/sources/image/ffmpeg/tiio_mp4.cpp index fb7d9a1..173d627 100644 --- a/toonz/sources/image/ffmpeg/tiio_mp4.cpp +++ b/toonz/sources/image/ffmpeg/tiio_mp4.cpp @@ -4,6 +4,7 @@ #include "trasterimage.h" #include "timageinfo.h" #include "tsound.h" +#include "toonz/stage.h" #include //=========================================================== @@ -129,8 +130,9 @@ class TImageReaderMp4 final : public TImageReader { public: int m_frameIndex; - TImageReaderMp4(const TFilePath &path, int index, TLevelReaderMp4 *lra) - : TImageReader(path), m_lra(lra), m_frameIndex(index) { + TImageReaderMp4(const TFilePath &path, int index, TLevelReaderMp4 *lra, + TImageInfo *info) + : TImageReader(path), m_lra(lra), m_frameIndex(index), m_info(info) { m_lra->addRef(); } ~TImageReaderMp4() { m_lra->release(); } @@ -138,9 +140,11 @@ public: TImageP load() override { return m_lra->load(m_frameIndex); } TDimension getSize() const { return m_lra->getSize(); } TRect getBBox() const { return TRect(); } + const TImageInfo *getImageInfo() const override { return m_info; } private: TLevelReaderMp4 *m_lra; + TImageInfo *m_info; // not implemented TImageReaderMp4(const TImageReaderMp4 &); @@ -173,6 +177,8 @@ TLevelReaderMp4::TLevelReaderMp4(const TFilePath &path) : TLevelReader(path) { m_info->m_ly = m_ly; m_info->m_bitsPerSample = 8; m_info->m_samplePerPixel = 4; + m_info->m_dpix = Stage::standardDpi; + m_info->m_dpiy = Stage::standardDpi; } //----------------------------------------------------------- @@ -197,7 +203,7 @@ TImageReaderP TLevelReaderMp4::getFrameReader(TFrameId fid) { if (fid.getLetter() != 0) return TImageReaderP(0); int index = fid.getNumber(); - TImageReaderMp4 *irm = new TImageReaderMp4(m_path, index, this); + TImageReaderMp4 *irm = new TImageReaderMp4(m_path, index, this, m_info); return TImageReaderP(irm); } diff --git a/toonz/sources/image/ffmpeg/tiio_webm.cpp b/toonz/sources/image/ffmpeg/tiio_webm.cpp index 0d9e2b2..d780061 100644 --- a/toonz/sources/image/ffmpeg/tiio_webm.cpp +++ b/toonz/sources/image/ffmpeg/tiio_webm.cpp @@ -4,6 +4,7 @@ #include "trasterimage.h" #include "tsound.h" #include "timageinfo.h" +#include "toonz/stage.h" #include //=========================================================== @@ -133,8 +134,9 @@ class TImageReaderWebm final : public TImageReader { public: int m_frameIndex; - TImageReaderWebm(const TFilePath &path, int index, TLevelReaderWebm *lra) - : TImageReader(path), m_lra(lra), m_frameIndex(index) { + TImageReaderWebm(const TFilePath &path, int index, TLevelReaderWebm *lra, + TImageInfo *info) + : TImageReader(path), m_lra(lra), m_frameIndex(index), m_info(info) { m_lra->addRef(); } ~TImageReaderWebm() { m_lra->release(); } @@ -142,9 +144,11 @@ public: TImageP load() override { return m_lra->load(m_frameIndex); } TDimension getSize() const { return m_lra->getSize(); } TRect getBBox() const { return TRect(); } + const TImageInfo *getImageInfo() const override { return m_info; } private: TLevelReaderWebm *m_lra; + TImageInfo *m_info; // not implemented TImageReaderWebm(const TImageReaderWebm &); @@ -177,6 +181,8 @@ TLevelReaderWebm::TLevelReaderWebm(const TFilePath &path) : TLevelReader(path) { m_info->m_ly = m_ly; m_info->m_bitsPerSample = 8; m_info->m_samplePerPixel = 4; + m_info->m_dpix = Stage::standardDpi; + m_info->m_dpiy = Stage::standardDpi; } //----------------------------------------------------------- @@ -201,7 +207,7 @@ TImageReaderP TLevelReaderWebm::getFrameReader(TFrameId fid) { if (fid.getLetter() != 0) return TImageReaderP(0); int index = fid.getNumber(); - TImageReaderWebm *irm = new TImageReaderWebm(m_path, index, this); + TImageReaderWebm *irm = new TImageReaderWebm(m_path, index, this, m_info); return TImageReaderP(irm); } diff --git a/toonz/sources/include/tcolorstyles.h b/toonz/sources/include/tcolorstyles.h index 1b999e7..2aecdad 100644 --- a/toonz/sources/include/tcolorstyles.h +++ b/toonz/sources/include/tcolorstyles.h @@ -118,6 +118,9 @@ private: // This flag will be set when the //! style is edited from the original one. + TPoint m_pickedPosition; // picked position from color model by using style + // picker tool with "organize palette" option. + protected: TRaster32P m_icon; //!< Icon shown on TPalette viewers. bool m_validIcon; //!< Icon's validity status. @@ -212,6 +215,9 @@ The \a global name contains information about palette id. m_flags = flags; } //!< Returns color attributes. + void setPickedPosition(const TPoint &pos) { m_pickedPosition = pos; } + TPoint getPickedPosition() const { return m_pickedPosition; } + // Color-related functions /*! \detail diff --git a/toonz/sources/include/tfilepath.h b/toonz/sources/include/tfilepath.h index ee04a45..0d58b5a 100644 --- a/toonz/sources/include/tfilepath.h +++ b/toonz/sources/include/tfilepath.h @@ -177,7 +177,7 @@ If the path is ":" a slash will be added*/ TFilePath getParentDir() const; // noSlash!; TFrameId getFrame() const; - + bool isFfmpegType() const; bool isLevelName() const; //{return getFrame() == TFrameId(TFrameId::EMPTY_FRAME);}; bool isAbsolute() const; diff --git a/toonz/sources/include/tools/cursors.h b/toonz/sources/include/tools/cursors.h index a912ffa..16eec82 100644 --- a/toonz/sources/include/tools/cursors.h +++ b/toonz/sources/include/tools/cursors.h @@ -66,6 +66,8 @@ enum { PickerCursorWhite, PickerCursorWhiteLine, PickerCursorWhiteArea, + PickerCursorOrganize, + PickerCursorWhiteOrganize, PickerRGB, PickerRGBWhite, diff --git a/toonz/sources/include/toonz/palettecmd.h b/toonz/sources/include/toonz/palettecmd.h index bca5440..ada5ee4 100644 --- a/toonz/sources/include/toonz/palettecmd.h +++ b/toonz/sources/include/toonz/palettecmd.h @@ -88,6 +88,17 @@ DVAPI void renamePalettePage(TPaletteHandle *paletteHandle, int pageIndex, DVAPI void renamePaletteStyle(TPaletteHandle *paletteHandle, const std::wstring &newName); +/* called in ColorModelViewer::pick() - move selected style to the first page */ +DVAPI void organizePaletteStyle(TPaletteHandle *paletteHandle, int styleId, + const TPoint &point); + +/* +called in ColorModelViewer::repickFromColorModel(). +Pick color from the img for all styles with "picked position" value. +*/ +DVAPI void pickColorByUsingPickedPosition(TPaletteHandle *paletteHandle, + TImageP img); + } // namespace #endif diff --git a/toonz/sources/include/toonz/preferences.h b/toonz/sources/include/toonz/preferences.h index ed3fa2c..56f7e3e 100644 --- a/toonz/sources/include/toonz/preferences.h +++ b/toonz/sources/include/toonz/preferences.h @@ -99,6 +99,14 @@ public: void setAutosavePeriod(int minutes); int getAutosavePeriod() const { return m_autosavePeriod; } // minutes + void enableAutosaveScene(bool on); + bool isAutosaveSceneEnabled() const { return m_autosaveSceneEnabled; } + + void enableAutosaveOtherFiles(bool on); + bool isAutosaveOtherFilesEnabled() const { + return m_autosaveOtherFilesEnabled; + } + void enableLevelsBackup(bool enabled); bool isLevelsBackupEnabled() const { return m_levelsBackupEnabled; } @@ -110,6 +118,15 @@ public: return m_replaceAfterSaveLevelAs; } + void enableStartupPopup(bool on); + bool isStartupPopupEnabled() { return m_startupPopupEnabled; } + + void setProjectRoot(int index); + int getProjectRoot() { return m_projectRoot; } + + void setCustomProjectRoot(std::wstring path); + QString getCustomProjectRoot() { return m_customProjectRoot; } + // Interface tab void setCurrentLanguage(int currentLanguage); @@ -406,6 +423,9 @@ public: int getTextureSize() const { return m_textureSize; } bool useDrawPixel() { return m_textureSize == 0; } + void setShortcutPreset(std::string preset); + QString getShortcutPreset() { return m_shortcutPreset; } + int getShmMax() const { return m_shmmax; } //! \sa The \p sysctl unix command. @@ -433,8 +453,8 @@ private: std::vector m_levelFormats; QString m_units, m_cameraUnits, m_scanLevelType, m_currentRoomChoice, - m_oldUnits, m_oldCameraUnits, m_ffmpegPath; - ; + m_oldUnits, m_oldCameraUnits, m_ffmpegPath, m_shortcutPreset, + m_customProjectRoot; double m_defLevelWidth, m_defLevelHeight, m_defLevelDpi; @@ -447,7 +467,7 @@ private: m_chunkSize, m_blanksCount, m_onionPaperThickness, m_step, m_shrink, m_textureSize, m_autocreationType, m_keyframeType, m_animationStep, m_ffmpegTimeout; // seconds - + int m_projectRoot; int m_currentLanguage, m_currentStyleSheet, m_undoMemorySize, // in megabytes m_dragCellsBehaviour, m_lineTestFpsCapture, m_defLevelType, m_xsheetStep, @@ -457,11 +477,13 @@ private: m_generatedMovieViewEnabled, m_xsheetAutopanEnabled, m_ignoreAlphaonColumn1Enabled, m_previewAlwaysOpenNewFlipEnabled, m_rewindAfterPlaybackEnabled, m_fitToFlipbookEnabled, m_autosaveEnabled, + m_autosaveSceneEnabled, m_autosaveOtherFilesEnabled, m_defaultViewerEnabled, m_pixelsOnly; bool m_rasterOptimizedMemory, m_saveUnpaintedInCleanup, m_askForOverrideRender, m_automaticSVNFolderRefreshEnabled, m_SVNEnabled, m_levelsBackupEnabled, m_minimizeSaveboxAfterEditing, - m_sceneNumberingEnabled, m_animationSheetEnabled, m_inksOnly; + m_sceneNumberingEnabled, m_animationSheetEnabled, m_inksOnly, + m_startupPopupEnabled; bool m_fillOnlySavebox, m_show0ThickLines, m_regionAntialias; bool m_onionSkinDuringPlayback; TPixel32 m_viewerBGColor, m_previewBGColor, m_chessboardColor1, diff --git a/toonz/sources/include/toonzqt/camerasettingswidget.h b/toonz/sources/include/toonzqt/camerasettingswidget.h index 18fc23b..1b2a995 100644 --- a/toonz/sources/include/toonzqt/camerasettingswidget.h +++ b/toonz/sources/include/toonzqt/camerasettingswidget.h @@ -71,6 +71,7 @@ protected: //--------------------------------------------------------------- class DVAPI CameraSettingsWidget final : public QFrame { + friend class StartupPopup; Q_OBJECT bool m_forCleanup; diff --git a/toonz/sources/include/toonzqt/dvdialog.h b/toonz/sources/include/toonzqt/dvdialog.h index b61e366..6184bf5 100644 --- a/toonz/sources/include/toonzqt/dvdialog.h +++ b/toonz/sources/include/toonzqt/dvdialog.h @@ -58,10 +58,11 @@ void DVAPI MsgBoxInPopup(MsgType type, const QString &text); // ATTENZIONE: Valore di ritorno // 0 = l'utente ha chiuso la finestra (dovrebbe corrispondere ad un cancel o ad -// un NO) -// 1 = primo bottone da sx premuto -// 2 = secondo bottone da sx premuto -// 3 = terzo bottone da sx premuto +// un NO) - closed window +// 1 = primo bottone da sx premuto - first button selected +// 2 = secondo bottone da sx premuto - second button +// 3 = terzo bottone da sx premuto - third button +// 4 = fourth button int DVAPI MsgBox(MsgType type, const QString &text, const std::vector &buttons, @@ -77,6 +78,12 @@ int DVAPI MsgBox(const QString &text, const QString &button1, const QString &button2, const QString &button3, int defaultButtonIndex = 0, QWidget *parent = 0); +// QUESTION: four botton user defined +int DVAPI MsgBox(const QString &text, const QString &button1, + const QString &button2, const QString &button3, + const QString &button4, int defaultButtonIndex = 0, + QWidget *parent = 0); + Dialog DVAPI *createMsgBox(MsgType type, const QString &text, const QStringList &buttons, int defaultButtonIndex, QWidget *parent = 0); @@ -229,6 +236,8 @@ public: void addButtonBarWidget(QWidget *widget); void addButtonBarWidget(QWidget *first, QWidget *second); void addButtonBarWidget(QWidget *first, QWidget *second, QWidget *third); + void addButtonBarWidget(QWidget *first, QWidget *second, QWidget *third, + QWidget *fourth); void hideEvent(QHideEvent *event) override; diff --git a/toonz/sources/include/toonzqt/flipconsole.h b/toonz/sources/include/toonzqt/flipconsole.h index f7d54e6..5e7c32a 100644 --- a/toonz/sources/include/toonzqt/flipconsole.h +++ b/toonz/sources/include/toonzqt/flipconsole.h @@ -214,7 +214,8 @@ public: eFilledRaster = 0x4000000, // Used only in LineTest eDefineLoadBox = 0x8000000, eUseLoadBox = 0x10000000, - eEnd = 0x20000000 + eLocator = 0x20000000, + eEnd = 0x40000000 }; static const UINT cFullConsole = eEnd - 1; diff --git a/toonz/sources/include/toonzqt/menubarcommand.h b/toonz/sources/include/toonzqt/menubarcommand.h index 869b1be..b1b677b 100644 --- a/toonz/sources/include/toonzqt/menubarcommand.h +++ b/toonz/sources/include/toonzqt/menubarcommand.h @@ -145,7 +145,8 @@ public: std::string getShortcutFromId(CommandId id); int getKeyFromShortcut(const std::string &shortcut); int getKeyFromId(CommandId id); - void setShortcut(QAction *action, std::string shortcutString); + void setShortcut(QAction *action, std::string shortcutString, + bool keepDefault = true); QAction *getAction(CommandId id, bool createIfNeeded = false); diff --git a/toonz/sources/include/toonzqt/paletteviewergui.h b/toonz/sources/include/toonzqt/paletteviewergui.h index 1d88c1c..e853458 100644 --- a/toonz/sources/include/toonzqt/paletteviewergui.h +++ b/toonz/sources/include/toonzqt/paletteviewergui.h @@ -201,12 +201,6 @@ protected: bool hasShortcut(int indexInPage); -protected slots: - - void toggleLink(); - void eraseToggleLink(); - void removeLink(); - private: DVGui::LineEdit *m_renameTextField; QPoint m_dragStartPosition; diff --git a/toonz/sources/include/toonzqt/selectioncommandids.h b/toonz/sources/include/toonzqt/selectioncommandids.h index 0dd6b73..99ebe5e 100644 --- a/toonz/sources/include/toonzqt/selectioncommandids.h +++ b/toonz/sources/include/toonzqt/selectioncommandids.h @@ -12,6 +12,8 @@ #define MI_PasteColors "MI_PasteColors" #define MI_PasteNames "MI_PasteNames" #define MI_GetColorFromStudioPalette "MI_GetColorFromStudioPalette" +#define MI_ToggleLinkToStudioPalette "MI_ToggleLinkToStudioPalette" +#define MI_RemoveReferenceToStudioPalette "MI_RemoveReferenceToStudioPalette" #define MI_Clear "MI_Clear" #define MI_SelectAll "MI_SelectAll" #define MI_InvertSelection "MI_InvertSelection" diff --git a/toonz/sources/include/toonzqt/styleselection.h b/toonz/sources/include/toonzqt/styleselection.h index fb78637..6e5099e 100644 --- a/toonz/sources/include/toonzqt/styleselection.h +++ b/toonz/sources/include/toonzqt/styleselection.h @@ -95,9 +95,11 @@ public: void toggleKeyframe(int frame); // remove link from the studio palette (if linked) - bool removeLink(); + void removeLink(); // get back the style from the studio palette (if linked) void getBackOriginalStyle(); + // return true if there is at least one linked style in the selection + bool hasLinkedStyle(); }; #endif // STYLESELECTION_INCLUDED diff --git a/toonz/sources/include/tpalette.h b/toonz/sources/include/tpalette.h index 339186f..e883e6d 100644 --- a/toonz/sources/include/tpalette.h +++ b/toonz/sources/include/tpalette.h @@ -420,6 +420,9 @@ between RGBA color components. m_isLocked = lock; } + bool hasPickedPosStyle(); // Returns true if there is at least one style with + // picked pos value + void nextShortcutScope(bool invert); public: diff --git a/toonz/sources/tcleanupper/tcleanupper.cpp b/toonz/sources/tcleanupper/tcleanupper.cpp index e133730..b750387 100644 --- a/toonz/sources/tcleanupper/tcleanupper.cpp +++ b/toonz/sources/tcleanupper/tcleanupper.cpp @@ -63,8 +63,8 @@ inline ostream &operator<<(ostream &out, const TFilePath &fp) { namespace { const char *applicationName = "OpenToonz"; -const char *applicationVersion = "1.0"; -const char *applicationFullName = "OpenToonz 1.0"; +const char *applicationVersion = "1.1"; +const char *applicationFullName = "OpenToonz 1.1"; const char *rootVarName = "TOONZROOT"; const char *systemVarPrefix = "TOONZ"; @@ -625,6 +625,14 @@ int main(int argc, char *argv[]) { /*-- CleanupSettingsファイルパスを直接入力した場合 --*/ else { try { + TProjectManager *pm = TProjectManager::instance(); + TProjectP sceneProject = pm->loadSceneProject(fp); + if (!sceneProject) { + cerr << "can't open project." << endl; + return -3; + } + scene->setProject(sceneProject.getPointer()); + /*- CleanupSettingsファイルに対応するTIFファイルが有るかチェック -*/ TFilePath tifImagePath = fp.withType("tif"); std::wcout << L"tifImagePath : " << tifImagePath.getWideString() diff --git a/toonz/sources/tcomposer/tcomposer.cpp b/toonz/sources/tcomposer/tcomposer.cpp index 676857a..1eb9d32 100644 --- a/toonz/sources/tcomposer/tcomposer.cpp +++ b/toonz/sources/tcomposer/tcomposer.cpp @@ -104,8 +104,8 @@ namespace { // const char *applicationName = "OpenToonz"; -const char *applicationVersion = "1.0"; -const char *applicationFullName = "OpenToonz 1.0"; +const char *applicationVersion = "1.1"; +const char *applicationFullName = "OpenToonz 1.1"; const char *rootVarName = "TOONZROOT"; const char *systemVarPrefix = "TOONZ"; diff --git a/toonz/sources/tconverter/tconverter.cpp b/toonz/sources/tconverter/tconverter.cpp index 31ae9c0..8b437aa 100644 --- a/toonz/sources/tconverter/tconverter.cpp +++ b/toonz/sources/tconverter/tconverter.cpp @@ -37,7 +37,7 @@ typedef QualifierT FilePathQualifier; #define RENDER_LICENSE_NOT_FOUND 888 -const char *applicationVersion = "1.0"; +const char *applicationVersion = "1.1"; const char *applicationName = "OpenToonz"; const char *rootVarName = "TOONZROOT"; const char *systemVarPrefix = "TOONZ"; diff --git a/toonz/sources/tnztools/CMakeLists.txt b/toonz/sources/tnztools/CMakeLists.txt index b3d5525..8f2b1c2 100644 --- a/toonz/sources/tnztools/CMakeLists.txt +++ b/toonz/sources/tnztools/CMakeLists.txt @@ -11,6 +11,7 @@ set(MOC_HEADERS ../include/tools/screenpicker.h rgbpickertool.h rulertool.h + stylepickertool.h ) set(HEADERS ${MOC_HEADERS} diff --git a/toonz/sources/tnztools/Resources/picker_style_organize.png b/toonz/sources/tnztools/Resources/picker_style_organize.png new file mode 100644 index 0000000..c502b37 Binary files /dev/null and b/toonz/sources/tnztools/Resources/picker_style_organize.png differ diff --git a/toonz/sources/tnztools/Resources/picker_style_white_organize.png b/toonz/sources/tnztools/Resources/picker_style_white_organize.png new file mode 100644 index 0000000..b905466 Binary files /dev/null and b/toonz/sources/tnztools/Resources/picker_style_white_organize.png differ diff --git a/toonz/sources/tnztools/brushtool.cpp b/toonz/sources/tnztools/brushtool.cpp index 3272da2..1585aa8 100644 --- a/toonz/sources/tnztools/brushtool.cpp +++ b/toonz/sources/tnztools/brushtool.cpp @@ -45,7 +45,7 @@ using namespace ToolUtils; TEnv::DoubleVar VectorBrushMinSize("InknpaintVectorBrushMinSize", 1); TEnv::DoubleVar VectorBrushMaxSize("InknpaintVectorBrushMaxSize", 5); -TEnv::IntVar VectorCapStyle("InknpaintVectorCapStyle", 0); +TEnv::IntVar VectorCapStyle("InknpaintVectorCapStyle", 1); TEnv::IntVar VectorJoinStyle("InknpaintVectorJoinStyle", 0); TEnv::IntVar VectorMiterValue("InknpaintVectorMiterValue", 4); TEnv::DoubleVar RasterBrushMinSize("InknpaintRasterBrushMinSize", 1); diff --git a/toonz/sources/tnztools/cursormanager.cpp b/toonz/sources/tnztools/cursormanager.cpp index 126610f..323ba47 100644 --- a/toonz/sources/tnztools/cursormanager.cpp +++ b/toonz/sources/tnztools/cursormanager.cpp @@ -73,6 +73,9 @@ const struct { {ToolCursor::PickerCursorWhiteLine, "picker_style_white_line", 7, 22}, {ToolCursor::PickerCursorWhiteArea, "picker_style_white_area", 7, 22}, {ToolCursor::PickerCursorWhite, "picker_style_white", 7, 22}, + {ToolCursor::PickerCursorOrganize, "picker_style_organize", 7, 22}, + {ToolCursor::PickerCursorWhiteOrganize, "picker_style_white_organize", 7, + 22}, {ToolCursor::PickerRGB, "picker_rgb", 7, 22}, {ToolCursor::PickerRGBWhite, "picker_rgb_white", 7, 22}, {ToolCursor::FillCursorF, "fill_f", 6, 23}, diff --git a/toonz/sources/tnztools/stylepickertool.cpp b/toonz/sources/tnztools/stylepickertool.cpp index e73625c..4c21641 100644 --- a/toonz/sources/tnztools/stylepickertool.cpp +++ b/toonz/sources/tnztools/stylepickertool.cpp @@ -1,238 +1,307 @@ +#include "stylepickertool.h" - +// TnzTools includes #include "tools/tool.h" #include "tools/cursors.h" #include "tools/stylepicker.h" -#include "toonz/txshsimplelevel.h" -#include "toonz/txshlevelhandle.h" +#include "tools/toolhandle.h" -#include "drawutil.h" -#include "tvectorimage.h" -#include "ttoonzimage.h" -#include "tundo.h" +// TnzQt includes +#include "toonzqt/tselectionhandle.h" +#include "toonzqt/styleselection.h" +// TnzLib includes +#include "toonz/txshsimplelevel.h" +#include "toonz/txshlevelhandle.h" #include "toonz/tpalettehandle.h" - #include "toonz/stage2.h" -#include "tproperty.h" -#include "toonzqt/tselectionhandle.h" -#include "toonzqt/styleselection.h" -#include "tools/toolhandle.h" #include "toonz/tframehandle.h" #include "toonz/txsheethandle.h" #include "toonz/preferences.h" #include "toonz/tcolumnhandle.h" #include "toonz/dpiscale.h" #include "toonz/palettecontroller.h" +#include "toonz/txshleveltypes.h" +#include "toonz/txshpalettelevel.h" + +// TnzCore includes +#include "drawutil.h" +#include "tvectorimage.h" +#include "ttoonzimage.h" +#include "tundo.h" +#include "tmsgcore.h" #define LINES L"Lines" #define AREAS L"Areas" #define ALL L"Lines & Areas" -namespace { - //======================================================================== // Pick Style Tool //------------------------------------------------------------------------ -class StylePickerTool final : public TTool { - int m_oldStyleId, m_currentStyleId; - - TEnumProperty m_colorType; - TPropertyGroup m_prop; - - TBoolProperty m_passivePick; +StylePickerTool::StylePickerTool() + : TTool("T_StylePicker") + , m_currentStyleId(0) + , m_colorType("Mode:") + , m_passivePick("Passive Pick", false) + , m_organizePalette("Organize Palette", false) + , m_paletteToBeOrganized(NULL) { + m_prop.bind(m_colorType); + m_colorType.addValue(AREAS); + m_colorType.addValue(LINES); + m_colorType.addValue(ALL); + m_colorType.setId("Mode"); + bind(TTool::CommonLevels); + + m_prop.bind(m_passivePick); + m_passivePick.setId("PassivePick"); + + m_prop.bind(m_organizePalette); + m_organizePalette.setId("OrganizePalette"); +} -public: - TPropertyGroup *getProperties(int targetType) override { return &m_prop; } +void StylePickerTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) { + m_oldStyleId = m_currentStyleId = + getApplication()->getCurrentLevelStyleIndex(); + pick(pos, e); +} - StylePickerTool() - : TTool("T_StylePicker") - , m_currentStyleId(0) - , m_colorType("Mode:") - , m_passivePick("Passive Pick", false) { - m_prop.bind(m_colorType); - m_colorType.addValue(AREAS); - m_colorType.addValue(LINES); - m_colorType.addValue(ALL); - m_colorType.setId("Mode"); - bind(TTool::CommonLevels); +void StylePickerTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { + pick(pos, e); +} - m_prop.bind(m_passivePick); - m_passivePick.setId("PassivePick"); +void StylePickerTool::pick(const TPointD &pos, const TMouseEvent &e) { + // Area = 0, Line = 1, All = 2 + int modeValue = m_colorType.getIndex(); + + //------------------------------------ + // MultiLayerStylePicker + /*--- + PickしたStyleId = 0、かつ + Preference で MultiLayerStylePickerが有効、かつ + Scene編集モード、かつ + 下のカラムから拾った色がTransparentでない場合、 + → カレントLevelを移動する。 + ---*/ + if (Preferences::instance()->isMultiLayerStylePickerEnabled() && + getApplication()->getCurrentFrame()->isEditingScene()) { + int superPickedColumnId = getViewer()->posToColumnIndex( + e.m_pos, getPixelSize() * getPixelSize(), false); + + if (superPickedColumnId >= 0 /*-- 何かColumnに当たった場合 --*/ + && + getApplication()->getCurrentColumn()->getColumnIndex() != + superPickedColumnId) /*-- かつ、Current Columnでない場合 --*/ + { + /*-- そのColumnからPickを試みる --*/ + int currentFrame = getApplication()->getCurrentFrame()->getFrame(); + TXshCell pickedCell = + getApplication()->getCurrentXsheet()->getXsheet()->getCell( + currentFrame, superPickedColumnId); + TImageP pickedImage = pickedCell.getImage(false).getPointer(); + TToonzImageP picked_ti = pickedImage; + TVectorImageP picked_vi = pickedImage; + TXshSimpleLevel *picked_level = pickedCell.getSimpleLevel(); + if ((picked_ti || picked_vi) && picked_level) { + TPointD tmpMousePosition = getColumnMatrix(superPickedColumnId).inv() * + getViewer()->winToWorld(e.m_pos); + + TPointD tmpDpiScale = getCurrentDpiScale(picked_level, getCurrentFid()); + + tmpMousePosition.x /= tmpDpiScale.x; + tmpMousePosition.y /= tmpDpiScale.y; + + StylePicker superPicker(pickedImage); + int picked_subsampling = + picked_level->getImageSubsampling(pickedCell.getFrameId()); + int superPicked_StyleId = superPicker.pickStyleId( + TScale(1.0 / picked_subsampling) * tmpMousePosition + + TPointD(-0.5, -0.5), + getPixelSize() * getPixelSize(), modeValue); + /*-- 何かStyleが拾えて、Transparentでない場合 --*/ + if (superPicked_StyleId > 0) { + /*-- Levelの移動 --*/ + getApplication()->getCurrentLevel()->setLevel(picked_level); + /*-- Columnの移動 --*/ + getApplication()->getCurrentColumn()->setColumnIndex( + superPickedColumnId); + /*-- 選択の解除 --*/ + if (getApplication()->getCurrentSelection()->getSelection()) + getApplication() + ->getCurrentSelection() + ->getSelection() + ->selectNone(); + /*-- StyleIdの移動 --*/ + getApplication()->setCurrentLevelStyleIndex(superPicked_StyleId); + return; + } + } + } + } + /*-- MultiLayerStylePicker ここまで --*/ + //------------------------------------ + TImageP image = getImage(false); + TToonzImageP ti = image; + TVectorImageP vi = image; + TXshSimpleLevel *level = + getApplication()->getCurrentLevel()->getSimpleLevel(); + if ((!ti && !vi) || !level) return; + + /*-- 画面外をpickしても拾えないようにする --*/ + if (!m_viewer->getGeometry().contains(pos)) return; + + int subsampling = level->getImageSubsampling(getCurrentFid()); + StylePicker picker(image); + int styleId = + picker.pickStyleId(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5), + getPixelSize() * getPixelSize(), modeValue); + + if (styleId < 0) return; + + if (modeValue == 1) // LINES + { + /*-- pickLineモードのとき、取得Styleが0の場合はカレントStyleを変えない。 + * --*/ + if (styleId == 0) return; + /*-- + * pickLineモードのとき、PurePaintの部分をクリックしてもカレントStyleを変えない + * --*/ + if (ti && + picker.pickTone(TScale(1.0 / subsampling) * pos + + TPointD(-0.5, -0.5)) == 255) + return; } - ToolType getToolType() const override { return TTool::LevelReadTool; } + /*--- Styleを選択している場合は選択を解除する ---*/ + TSelection *selection = + TTool::getApplication()->getCurrentSelection()->getSelection(); + if (selection) { + TStyleSelection *styleSelection = + dynamic_cast(selection); + if (styleSelection) styleSelection->selectNone(); + } - void draw() override {} + getApplication()->setCurrentLevelStyleIndex(styleId); +} - void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override { - m_oldStyleId = m_currentStyleId = - getApplication()->getCurrentLevelStyleIndex(); - pick(pos, e); - } - void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override { - pick(pos, e); +void StylePickerTool::mouseMove(const TPointD &pos, const TMouseEvent &e) { + if (!m_passivePick.getValue()) return; + /*--- PassiveにStyleを拾う機能 ---*/ + PaletteController *controller = + TTool::getApplication()->getPaletteController(); + + TImageP image = getImage(false); + TToonzImageP ti = image; + TVectorImageP vi = image; + TXshSimpleLevel *level = + getApplication()->getCurrentLevel()->getSimpleLevel(); + if ((!ti && !vi) || !level || !m_viewer->getGeometry().contains(pos)) { + controller->notifyStylePassivePicked(-1, -1, -1); + return; } - void pick(const TPointD &pos, const TMouseEvent &e) { - // Area = 0, Line = 1, All = 2 - int modeValue = m_colorType.getIndex(); - - //------------------------------------ - // MultiLayerStylePicker - /*--- - PickしたStyleId = 0、かつ - Preference で MultiLayerStylePickerが有効、かつ - Scene編集モード、かつ - 下のカラムから拾った色がTransparentでない場合、 - → カレントLevelを移動する。 - ---*/ - if (Preferences::instance()->isMultiLayerStylePickerEnabled() && - getApplication()->getCurrentFrame()->isEditingScene()) { - int superPickedColumnId = getViewer()->posToColumnIndex( - e.m_pos, getPixelSize() * getPixelSize(), false); - - if (superPickedColumnId >= 0 /*-- 何かColumnに当たった場合 --*/ - && - getApplication()->getCurrentColumn()->getColumnIndex() != - superPickedColumnId) /*-- かつ、Current Columnでない場合 --*/ - { - /*-- そのColumnからPickを試みる --*/ - int currentFrame = getApplication()->getCurrentFrame()->getFrame(); - TXshCell pickedCell = - getApplication()->getCurrentXsheet()->getXsheet()->getCell( - currentFrame, superPickedColumnId); - TImageP pickedImage = pickedCell.getImage(false).getPointer(); - TToonzImageP picked_ti = pickedImage; - TVectorImageP picked_vi = pickedImage; - TXshSimpleLevel *picked_level = pickedCell.getSimpleLevel(); - if ((picked_ti || picked_vi) && picked_level) { - TPointD tmpMousePosition = - getColumnMatrix(superPickedColumnId).inv() * - getViewer()->winToWorld(e.m_pos); - - TPointD tmpDpiScale = - getCurrentDpiScale(picked_level, getCurrentFid()); - - tmpMousePosition.x /= tmpDpiScale.x; - tmpMousePosition.y /= tmpDpiScale.y; - - StylePicker superPicker(pickedImage); - int picked_subsampling = - picked_level->getImageSubsampling(pickedCell.getFrameId()); - int superPicked_StyleId = superPicker.pickStyleId( - TScale(1.0 / picked_subsampling) * tmpMousePosition + - TPointD(-0.5, -0.5), - getPixelSize() * getPixelSize(), modeValue); - /*-- 何かStyleが拾えて、Transparentでない場合 --*/ - if (superPicked_StyleId > 0) { - /*-- Levelの移動 --*/ - getApplication()->getCurrentLevel()->setLevel(picked_level); - /*-- Columnの移動 --*/ - getApplication()->getCurrentColumn()->setColumnIndex( - superPickedColumnId); - /*-- 選択の解除 --*/ - if (getApplication()->getCurrentSelection()->getSelection()) - getApplication() - ->getCurrentSelection() - ->getSelection() - ->selectNone(); - /*-- StyleIdの移動 --*/ - getApplication()->setCurrentLevelStyleIndex(superPicked_StyleId); - return; - } - } - } - } - /*-- MultiLayerStylePicker ここまで --*/ - //------------------------------------ - TImageP image = getImage(false); - TToonzImageP ti = image; - TVectorImageP vi = image; - TXshSimpleLevel *level = - getApplication()->getCurrentLevel()->getSimpleLevel(); - if ((!ti && !vi) || !level) return; - - /*-- 画面外をpickしても拾えないようにする --*/ - if (!m_viewer->getGeometry().contains(pos)) return; - - int subsampling = level->getImageSubsampling(getCurrentFid()); - StylePicker picker(image); - int styleId = picker.pickStyleId( - TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5), - getPixelSize() * getPixelSize(), modeValue); - - if (styleId < 0) return; - - if (modeValue == 1) // LINES - { - /*-- pickLineモードのとき、取得Styleが0の場合はカレントStyleを変えない。 - * --*/ - if (styleId == 0) return; - /*-- - * pickLineモードのとき、PurePaintの部分をクリックしてもカレントStyleを変えない - * --*/ - if (ti && - picker.pickTone(TScale(1.0 / subsampling) * pos + - TPointD(-0.5, -0.5)) == 255) - return; - } - - /*--- Styleを選択している場合は選択を解除する ---*/ - TSelection *selection = - TTool::getApplication()->getCurrentSelection()->getSelection(); - if (selection) { - TStyleSelection *styleSelection = - dynamic_cast(selection); - if (styleSelection) styleSelection->selectNone(); - } + int subsampling = level->getImageSubsampling(getCurrentFid()); + StylePicker picker(image); + TPointD pickPos(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5)); + int inkStyleId = + picker.pickStyleId(pickPos, getPixelSize() * getPixelSize(), 1); + int paintStyleId = + picker.pickStyleId(pickPos, getPixelSize() * getPixelSize(), 0); + int tone = picker.pickTone(pickPos); + controller->notifyStylePassivePicked(inkStyleId, paintStyleId, tone); +} - getApplication()->setCurrentLevelStyleIndex(styleId); - } +int StylePickerTool::getCursorId() const { + bool isBlackBG = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg; + + /* in case the "organize palette" option is active */ + if (m_organizePalette.getValue()) + return (isBlackBG) ? ToolCursor::PickerCursorWhiteOrganize + : ToolCursor::PickerCursorOrganize; + + if (m_colorType.getValue() == LINES) + return (isBlackBG) ? ToolCursor::PickerCursorWhiteLine + : ToolCursor::PickerCursorLine; + else if (m_colorType.getValue() == AREAS) + return (isBlackBG) ? ToolCursor::PickerCursorWhiteArea + : ToolCursor::PickerCursorArea; + else // line&areas + return (isBlackBG) ? ToolCursor::PickerCursorWhite + : ToolCursor::PickerCursor; +} - void mouseMove(const TPointD &pos, const TMouseEvent &e) override { - if (!m_passivePick.getValue()) return; - /*--- PassiveにStyleを拾う機能 ---*/ - PaletteController *controller = - TTool::getApplication()->getPaletteController(); - - TImageP image = getImage(false); - TToonzImageP ti = image; - TVectorImageP vi = image; - TXshSimpleLevel *level = - getApplication()->getCurrentLevel()->getSimpleLevel(); - if ((!ti && !vi) || !level || !m_viewer->getGeometry().contains(pos)) { - controller->notifyStylePassivePicked(-1, -1, -1); - return; +bool StylePickerTool::onPropertyChanged(std::string propertyName) { + if (propertyName == m_organizePalette.getName()) { + if (m_organizePalette.getValue()) { + if (!startOrganizePalette()) { + m_organizePalette.setValue(false); + getApplication()->getCurrentTool()->notifyToolChanged(); + return false; + } + } else { + std::cout << "End Organize Palette" << std::endl; + m_paletteToBeOrganized = NULL; } + } + return true; +} - int subsampling = level->getImageSubsampling(getCurrentFid()); - StylePicker picker(image); - TPointD pickPos(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5)); - int inkStyleId = - picker.pickStyleId(pickPos, getPixelSize() * getPixelSize(), 1); - int paintStyleId = - picker.pickStyleId(pickPos, getPixelSize() * getPixelSize(), 0); - int tone = picker.pickTone(pickPos); - controller->notifyStylePassivePicked(inkStyleId, paintStyleId, tone); +bool StylePickerTool::startOrganizePalette() { + /* Check if the organizing operation is available */ + TXshLevel *level = getApplication()->getCurrentLevel()->getLevel(); + if (!level) { + DVGui::error(tr("No current level.")); + return false; + } + if (level->getType() != PLI_XSHLEVEL && level->getType() != TZP_XSHLEVEL && + level->getType() != PLT_XSHLEVEL) { + DVGui::error(tr("Current level has no available palette.")); + return false; + } + /* palette should have more than one page to organize */ + TPalette *pal = NULL; + if (level->getType() == PLT_XSHLEVEL) + pal = level->getPaletteLevel()->getPalette(); + else + pal = level->getSimpleLevel()->getPalette(); + if (!pal || pal->getPageCount() < 2) { + DVGui::error( + tr("Palette must have more than one palette to be organized.")); + return false; } - void onActivate() override {} + m_paletteToBeOrganized = pal; - int getCursorId() const override { - bool isBlackBG = ToonzCheck::instance()->getChecks() & ToonzCheck::eBlackBg; + std::cout << "Start Organize Palette" << std::endl; - if (m_colorType.getValue() == LINES) - return (isBlackBG) ? ToolCursor::PickerCursorWhiteLine - : ToolCursor::PickerCursorLine; - else if (m_colorType.getValue() == AREAS) - return (isBlackBG) ? ToolCursor::PickerCursorWhiteArea - : ToolCursor::PickerCursorArea; - else // line&areas - return (isBlackBG) ? ToolCursor::PickerCursorWhite - : ToolCursor::PickerCursor; - } + return true; +} -} stylePickerTool; +/* + If the working palette is changed, then deactivate the "organize palette" + toggle. +*/ +void StylePickerTool::onImageChanged() { + std::cout << "StylePickerTool::onImageChanged" << std::endl; + if (!m_organizePalette.getValue() || !m_paletteToBeOrganized) return; + + TXshLevel *level = getApplication()->getCurrentLevel()->getLevel(); + if (!level) { + m_organizePalette.setValue(false); + getApplication()->getCurrentTool()->notifyToolChanged(); + return; + } + TPalette *pal = NULL; + if (level->getType() == PLT_XSHLEVEL) + pal = level->getPaletteLevel()->getPalette(); + else if (level->getSimpleLevel()) { + pal = level->getSimpleLevel()->getPalette(); + } + if (!pal || pal != m_paletteToBeOrganized) { + m_organizePalette.setValue(false); + getApplication()->getCurrentTool()->notifyToolChanged(); + return; + } } + +StylePickerTool stylePickerTool; diff --git a/toonz/sources/tnztools/stylepickertool.h b/toonz/sources/tnztools/stylepickertool.h new file mode 100644 index 0000000..2a6982a --- /dev/null +++ b/toonz/sources/tnztools/stylepickertool.h @@ -0,0 +1,54 @@ +#pragma once + +#ifndef STYLEPICKERTOOL_H +#define STYLEPICKERTOOL_H + +#include "tools/tool.h" +#include "tproperty.h" +#include + +class StylePickerTool final : public TTool, public QObject { + int m_oldStyleId, m_currentStyleId; + + TEnumProperty m_colorType; + TPropertyGroup m_prop; + TBoolProperty m_passivePick; + + TBoolProperty m_organizePalette; + TPalette *m_paletteToBeOrganized; + + bool startOrganizePalette(); + +public: + TPropertyGroup *getProperties(int targetType) override { return &m_prop; } + + StylePickerTool(); + + ToolType getToolType() const override { return TTool::LevelReadTool; } + + void draw() override {} + + void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override; + + void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override; + + void pick(const TPointD &pos, const TMouseEvent &e); + + void mouseMove(const TPointD &pos, const TMouseEvent &e) override; + + int getCursorId() const override; + + bool onPropertyChanged(std::string propertyName); + + bool isOrganizePaletteActive() { return m_organizePalette.getValue(); } + + /* + This function is called when either frame/column/level/scene is switched or + either scene/level/object is changed (see tapp.cpp). + If the working palette is changed, then deactivate the "organize palette" + toggle. + */ + void onImageChanged() override; +}; + +#endif \ No newline at end of file diff --git a/toonz/sources/tnztools/tnztools.qrc b/toonz/sources/tnztools/tnztools.qrc index 98087dc..1b5b91b 100644 --- a/toonz/sources/tnztools/tnztools.qrc +++ b/toonz/sources/tnztools/tnztools.qrc @@ -50,6 +50,8 @@ Resources/picker_style_white_line.png Resources/picker_style_white_area.png Resources/picker_style_white.png + Resources/picker_style_organize.png + Resources/picker_style_white_organize.png Resources/picker_rgb.png Resources/picker_rgb_white.png Resources/fill_f.png diff --git a/toonz/sources/tnztools/tooloptions.cpp b/toonz/sources/tnztools/tooloptions.cpp index d333ad4..399b876 100644 --- a/toonz/sources/tnztools/tooloptions.cpp +++ b/toonz/sources/tnztools/tooloptions.cpp @@ -2182,6 +2182,17 @@ StylePickerToolOptionsBox::StylePickerToolOptionsBox( m_layout->addWidget(m_currentStyleLabel, 0); m_layout->addStretch(1); + // retrieve the "organize palette" checkbox from the layout and insert + // into rightmost of the tool option bar + ToolOptionCheckbox *organizePaletteCB = + dynamic_cast(m_controls.value("Organize Palette")); + m_layout->removeWidget(organizePaletteCB); + m_layout->addWidget(new ToolOptionsBarSeparator(this), 0); + m_layout->addWidget(organizePaletteCB); + organizePaletteCB->setToolTip( + tr("With this option being activated, the picked style will be\nmoved to " + "the end of the first page of the palette.")); + if (m_realTimePickMode) { connect(m_realTimePickMode, SIGNAL(toggled(bool)), m_currentStyleLabel, SLOT(setVisible(bool))); diff --git a/toonz/sources/toonz/CMakeLists.txt b/toonz/sources/toonz/CMakeLists.txt index 0215c13..62ee338 100644 --- a/toonz/sources/toonz/CMakeLists.txt +++ b/toonz/sources/toonz/CMakeLists.txt @@ -100,6 +100,7 @@ set(MOC_HEADERS selectionutils.h shifttracetool.h shortcutpopup.h + startuppopup.h subcameramanager.h subscenecommand.h svncleanupdialog.h @@ -140,6 +141,7 @@ set(MOC_HEADERS historypane.h cleanupsettingspane.h penciltestpopup.h + locatorpopup.h # Tracker file dummyprocessor.h metnum.h @@ -232,6 +234,7 @@ set(SOURCES scriptconsolepanel.cpp shifttracetool.cpp shortcutpopup.cpp + startuppopup.cpp subcameramanager.cpp timestretchpopup.cpp trackerpopup.cpp @@ -298,6 +301,7 @@ set(SOURCES historypane.cpp cleanupsettingspane.cpp penciltestpopup.cpp + locatorpopup.cpp # Tracker file dummyprocessor.cpp metnum.cpp @@ -374,11 +378,11 @@ if(WIN32) endif() endif() -if(WIN32) +if(WIN32) target_link_libraries(OpenToonz_${VERSION} 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} + ${GL_LIB} ${GLUT_LIB} strmiids tnzcore tnzbase toonzlib colorfx tnzext image sound toonzqt tnztools tnzstdfx tfarm ) elseif(APPLE) diff --git a/toonz/sources/toonz/Resources/locator.png b/toonz/sources/toonz/Resources/locator.png new file mode 100644 index 0000000..439df63 Binary files /dev/null and b/toonz/sources/toonz/Resources/locator.png differ diff --git a/toonz/sources/toonz/Resources/locator_click.png b/toonz/sources/toonz/Resources/locator_click.png new file mode 100644 index 0000000..8045221 Binary files /dev/null and b/toonz/sources/toonz/Resources/locator_click.png differ diff --git a/toonz/sources/toonz/Resources/locator_over.png b/toonz/sources/toonz/Resources/locator_over.png new file mode 100644 index 0000000..8045221 Binary files /dev/null and b/toonz/sources/toonz/Resources/locator_over.png differ diff --git a/toonz/sources/toonz/Resources/startup.png b/toonz/sources/toonz/Resources/startup.png new file mode 100644 index 0000000..10757e0 Binary files /dev/null and b/toonz/sources/toonz/Resources/startup.png differ diff --git a/toonz/sources/toonz/cellselectioncommand.cpp b/toonz/sources/toonz/cellselectioncommand.cpp index a670e73..fa3c108 100644 --- a/toonz/sources/toonz/cellselectioncommand.cpp +++ b/toonz/sources/toonz/cellselectioncommand.cpp @@ -1292,6 +1292,7 @@ TXshSimpleLevel *CloneLevelUndo::cloneLevel( assert(palette); dstSl->setPalette(palette->clone()); + dstSl->getPalette()->setDirtyFlag(true); } // The level clone shell was created. Now, clone the associated frames found @@ -1306,6 +1307,8 @@ TXshSimpleLevel *CloneLevelUndo::cloneLevel( dstSl->setFrame(*ft, img->cloneImage()); } + dstSl->setDirtyFlag(true); + return dstSl; } diff --git a/toonz/sources/toonz/cleanupsettingspane.cpp b/toonz/sources/toonz/cleanupsettingspane.cpp index d7e5579..30756ba 100644 --- a/toonz/sources/toonz/cleanupsettingspane.cpp +++ b/toonz/sources/toonz/cleanupsettingspane.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "cleanupsettingspane.h" @@ -80,6 +81,10 @@ void CleanupSaveInField::browseDirectory() { CleanupSettingsPane::CleanupSettingsPane(QWidget *parent) : QFrame(parent), m_attached(false) { + // Autocenter + m_autocenterBox = new QGroupBox(tr("Autocenter"), this); + m_pegHolesOm = new QComboBox(this); + m_fieldGuideOm = new QComboBox(this); // Rotate&Flip QFrame *rotFlipFrame = new QFrame(this); m_rotateOm = new QComboBox(this); @@ -103,6 +108,19 @@ CleanupSettingsPane::CleanupSettingsPane(QWidget *parent) QPushButton *loadBtn = new QPushButton(tr("Load")); QPushButton *resetBtn = new QPushButton(tr("Reset")); + // Autocenter + m_autocenterBox->setCheckable(true); + QStringList pegbarHoles; + pegbarHoles << "Bottom" + << "Top" + << "Left" + << "Right"; + m_pegHolesOm->addItems(pegbarHoles); + std::vector fdgNames; + CleanupParameters::getFdgNames(fdgNames); + for (int i = 0; i < (int)fdgNames.size(); i++) + m_fieldGuideOm->addItem(QString(fdgNames[i].c_str())); + // Rotate&Flip rotFlipFrame->setObjectName("CleanupSettingsFrame"); QStringList rotate; @@ -137,6 +155,23 @@ CleanupSettingsPane::CleanupSettingsPane(QWidget *parent) mainLay->setSpacing(2); mainLay->setMargin(5); { + // Autocenter + QGridLayout *autocenterLay = new QGridLayout(); + autocenterLay->setMargin(5); + autocenterLay->setSpacing(3); + { + autocenterLay->addWidget(new QLabel(tr("Pegbar Holes")), 0, 0, + Qt::AlignRight | Qt::AlignVCenter); + autocenterLay->addWidget(m_pegHolesOm, 0, 1); + autocenterLay->addWidget(new QLabel(tr("Field Guide")), 1, 0, + Qt::AlignRight | Qt::AlignVCenter); + autocenterLay->addWidget(m_fieldGuideOm, 1, 1); + } + autocenterLay->setColumnStretch(0, 0); + autocenterLay->setColumnStretch(1, 1); + m_autocenterBox->setLayout(autocenterLay); + mainLay->addWidget(m_autocenterBox, 0); + // Rotate&Flip QGridLayout *rotFlipLay = new QGridLayout(); rotFlipLay->setMargin(5); @@ -226,7 +261,14 @@ CleanupSettingsPane::CleanupSettingsPane(QWidget *parent) //-----signal-slot connections bool ret = true; - ret = ret && connect(m_rotateOm, SIGNAL(activated(int)), + ret = ret && connect(m_autocenterBox, SIGNAL(toggled(bool)), + SLOT(onGenericSettingsChange())); + ret = ret && connect(m_pegHolesOm, SIGNAL(activated(int)), + SLOT(onGenericSettingsChange())); + ret = ret && connect(m_fieldGuideOm, SIGNAL(activated(int)), + SLOT(onGenericSettingsChange())); + + ret = ret && connect(m_rotateOm, SIGNAL(activated(int)), SLOT(onGenericSettingsChange())); ret = ret && connect(m_flipX, SIGNAL(stateChanged(int)), SLOT(onGenericSettingsChange())); @@ -336,6 +378,15 @@ void CleanupSettingsPane::updateGui(bool needsPostProcess) { void CleanupSettingsPane::updateGui(CleanupParameters *params, CleanupParameters *oldParams) { + m_autocenterBox->setChecked(params->m_autocenterType == + CleanupTypes::AUTOCENTER_FDG); + m_pegHolesOm->setCurrentIndex(params->m_pegSide - 1); + + QString fieldName = QString::fromStdString(params->getFdgName()); + int index = (fieldName.isEmpty()) ? 0 : m_fieldGuideOm->findText(fieldName); + assert(index != -1); + m_fieldGuideOm->setCurrentIndex(index); + m_rotateOm->setCurrentIndex(params->m_rotate / 90); m_flipX->setChecked(params->m_flipx); m_flipY->setChecked(params->m_flipy); @@ -462,6 +513,13 @@ void CleanupSettingsPane::onGenericSettingsChange() { CleanupSettingsModel *model = CleanupSettingsModel::instance(); CleanupParameters *params = model->getCurrentParameters(); + params->m_autocenterType = m_autocenterBox->isChecked() + ? CleanupTypes::AUTOCENTER_FDG + : CleanupTypes::AUTOCENTER_NONE; + params->m_pegSide = + (CleanupTypes::PEGS_SIDE)(m_pegHolesOm->currentIndex() + 1); + params->setFdgByName(m_fieldGuideOm->currentText().toStdString()); + params->m_rotate = m_rotateOm->currentIndex() * 90; params->m_flipx = m_flipX->isChecked(); params->m_flipy = m_flipY->isChecked(); diff --git a/toonz/sources/toonz/cleanupsettingspane.h b/toonz/sources/toonz/cleanupsettingspane.h index b0069d8..75da278 100644 --- a/toonz/sources/toonz/cleanupsettingspane.h +++ b/toonz/sources/toonz/cleanupsettingspane.h @@ -18,6 +18,7 @@ class QComboBox; class QLabel; class QCheckBox; class CleanupPaletteViewer; +class QGroupBox; namespace DVGui { @@ -47,6 +48,9 @@ public: CleanupCameraSettingsWidget *m_cameraWidget; private: + //----Autocenter + QGroupBox *m_autocenterBox; + QComboBox *m_pegHolesOm, *m_fieldGuideOm; //----Rotate & Flip QComboBox *m_rotateOm; QCheckBox *m_flipX; diff --git a/toonz/sources/toonz/colormodelviewer.cpp b/toonz/sources/toonz/colormodelviewer.cpp index 2e063b5..e4b0085 100644 --- a/toonz/sources/toonz/colormodelviewer.cpp +++ b/toonz/sources/toonz/colormodelviewer.cpp @@ -14,6 +14,7 @@ #include "tools/toolcommandids.h" #include "tools/tool.h" #include "tools/toolhandle.h" +#include "../tnztools/stylepickertool.h" // TnzQt includes #include "toonzqt/menubarcommand.h" @@ -84,7 +85,7 @@ ColorModelViewer::ColorModelViewer(QWidget *parent) FlipConsole::eCompare | FlipConsole::eCustomize | FlipConsole::eSave | FlipConsole::eFilledRaster | FlipConsole::eDefineLoadBox | FlipConsole::eUseLoadBox | - FlipConsole::eDefineSubCamera)), + FlipConsole::eDefineSubCamera | FlipConsole::eLocator)), eDontKeepFilesOpened, true) , m_mode(0) , m_currentRefImgPath(TFilePath()) { @@ -222,11 +223,28 @@ void ColorModelViewer::contextMenuEvent(QContextMenuEvent *event) { connect(loadCurrentFrame, SIGNAL(triggered()), SLOT(loadCurrentFrame())); menu.addAction(loadCurrentFrame); + if (!m_imageViewer->getImage()) { + menu.exec(event->globalPos()); + return; + } + QAction *removeColorModel = new QAction(QString(tr("Remove Color Model")), this); connect(removeColorModel, SIGNAL(triggered()), SLOT(removeColorModel())); menu.addAction(removeColorModel); + /* If there is at least one style with "picked pos" parameter, then enable + * repick command */ + TRasterImageP ri = m_imageViewer->getImage(); + if (ri && currentPalette->hasPickedPosStyle()) { + menu.addSeparator(); + QAction *repickFromColorModelAct = new QAction( + QString(tr("Update Colors by Using Picked Positions")), this); + connect(repickFromColorModelAct, SIGNAL(triggered()), + SLOT(repickFromColorModel())); + menu.addAction(repickFromColorModelAct); + } + menu.addSeparator(); QString shortcut = QString::fromStdString( @@ -306,6 +324,19 @@ void ColorModelViewer::pick(const QPoint &p) { if (styleSelection) styleSelection->selectNone(); } + /* + if the Style Picker tool is current and "organize palette" is activated, + then move the picked style to the first page of the palette. + */ + TTool *tool = TApp::instance()->getCurrentTool()->getTool(); + if (tool->getName() == "T_StylePicker") { + StylePickerTool *spTool = dynamic_cast(tool); + if (spTool && spTool->isOrganizePaletteActive()) { + TPoint point = picker.getRasterPoint(pos); + PaletteCmd::organizePaletteStyle(ph, styleIndex, point); + } + } + ph->setStyleIndex(styleIndex); } @@ -356,8 +387,16 @@ void ColorModelViewer::showEvent(QShowEvent *e) { //----------------------------------------------------------------------------- /*- ツールのTypeに合わせてPickのタイプも変え、カーソルも切り替える -*/ void ColorModelViewer::changePickType() { - TPropertyGroup *propGroup = - TApp::instance()->getCurrentTool()->getTool()->getProperties(0); + TTool *tool = TApp::instance()->getCurrentTool()->getTool(); + if (tool->getName() == T_StylePicker) { + StylePickerTool *stylePickerTool = dynamic_cast(tool); + if (stylePickerTool->isOrganizePaletteActive()) { + setToolCursor(m_imageViewer, ToolCursor::PickerCursorOrganize); + return; + } + } + + TPropertyGroup *propGroup = tool->getProperties(0); /*- Propertyの無いツールの場合 -*/ if (!propGroup) { m_mode = 2; @@ -573,6 +612,17 @@ void ColorModelViewer::onRefImageNotFound() { "level.")); } +//----------------------------------------------------------------------------- + +void ColorModelViewer::repickFromColorModel() { + TImageP img = m_imageViewer->getImage(); + if (!img) return; + TPaletteHandle *ph = + TApp::instance()->getPaletteController()->getCurrentLevelPalette(); + + PaletteCmd::pickColorByUsingPickedPosition(ph, img); +} + //============================================================================= OpenFloatingPanel openColorModelCommand(MI_OpenColorModel, "ColorModel", diff --git a/toonz/sources/toonz/colormodelviewer.h b/toonz/sources/toonz/colormodelviewer.h index e068080..833a62d 100644 --- a/toonz/sources/toonz/colormodelviewer.h +++ b/toonz/sources/toonz/colormodelviewer.h @@ -48,6 +48,7 @@ protected: * UseCurrentFrameのLevelに移動してきたときに、改めてCurrentFrameを格納しなおす * -*/ void reloadCurrentFrame(); + protected slots: void showCurrentImage(); @@ -62,6 +63,8 @@ protected slots: * -*/ void changePickType(); + void repickFromColorModel(); + signals: void refImageNotFound(); }; diff --git a/toonz/sources/toonz/filebrowser.cpp b/toonz/sources/toonz/filebrowser.cpp index f4f06e8..73f7f9a 100644 --- a/toonz/sources/toonz/filebrowser.cpp +++ b/toonz/sources/toonz/filebrowser.cpp @@ -148,7 +148,8 @@ QMutex levelFileMutex; inline bool isMultipleFrameType(std::string type) { return (type == "tlv" || type == "tzl" || type == "pli" || type == "mov" || - type == "avi" || type == "3gp"); + type == "avi" || type == "3gp" || type == "gif" || type == "mp4" || + type == "webm"); } //============================================================================= diff --git a/toonz/sources/toonz/flipbook.h b/toonz/sources/toonz/flipbook.h index a116f3c..b9e13ee 100644 --- a/toonz/sources/toonz/flipbook.h +++ b/toonz/sources/toonz/flipbook.h @@ -179,7 +179,8 @@ public: FlipBook(QWidget *parent = 0, QString viewerTitle = QString(), UINT flipConsoleButtonMask = FlipConsole::cFullConsole & (~(FlipConsole::eFilledRaster | - FlipConsole::eDefineSubCamera)), + FlipConsole::eDefineSubCamera | + FlipConsole::eLocator)), UCHAR flags = 0, bool isColorModel = false); ~FlipBook(); void setLevel(const TFilePath &path, TPalette *palette = 0, int from = -1, diff --git a/toonz/sources/toonz/iocommand.cpp b/toonz/sources/toonz/iocommand.cpp index f1b35d0..2cb728d 100644 --- a/toonz/sources/toonz/iocommand.cpp +++ b/toonz/sources/toonz/iocommand.cpp @@ -1176,17 +1176,21 @@ bool IoCmd::saveSceneIfNeeded(QString msg) { QString question; question = QObject::tr( "%1: the current scene has been modified.\n" - "Do you want to save your changes?") + "What would you like to do?") .arg(msg); - int ret = DVGui::MsgBox(question, QObject::tr("Save"), - QObject::tr("Discard"), QObject::tr("Cancel"), 0); - if (ret == 0 || ret == 3) { + int ret = DVGui::MsgBox( + question, QObject::tr("Save All"), QObject::tr("Save Scene Only"), + QObject::tr("Discard Changes"), QObject::tr("Cancel"), 0); + if (ret == 0 || ret == 4) { // cancel (or closed message box window) return false; } else if (ret == 1) { + // save all + if (!IoCmd::saveAll()) return false; + } else if (ret == 2) { // save if (!IoCmd::saveScene()) return false; - } else if (ret == 2) { + } else if (ret == 3) { } isLevelOrSceneIsDirty = true; @@ -1203,21 +1207,25 @@ bool IoCmd::saveSceneIfNeeded(QString msg) { if (!dirtyResources.empty()) { QString question; - question = - msg + ":" + QObject::tr(" Following file(s) are modified.\n\n"); + question = msg + ":" + + QObject::tr(" The following file(s) have been modified.\n\n"); for (int i = 0; i < dirtyResources.size(); i++) { question += " " + dirtyResources[i] + "\n"; } - question += - QObject::tr("\nAre you sure to ") + msg + QObject::tr(" anyway ?"); + question += QObject::tr("\nWhat would you like to do? "); int ret = - DVGui::MsgBox(question, QObject::tr("OK"), QObject::tr("Cancel"), 0); - if (ret == 0 || ret == 2) { + DVGui::MsgBox(question, QObject::tr("Save Changes"), + msg + QObject::tr(" Anyway"), QObject::tr("Cancel"), 0); + if (ret == 0 || ret == 3) { // cancel (or closed message box window) return false; } else if (ret == 1) { - // ok + // save non scene files + IoCmd::saveNonSceneFiles(); + return false; + } else if (ret == 2) { + // quit } isLevelOrSceneIsDirty = true; @@ -1604,7 +1612,7 @@ bool IoCmd::saveLevel(TXshSimpleLevel *sl) { } //=========================================================================== -// IoCmd::saveSound(soundPath, soundColumn, overwrite) +// IoCmd::saveAll() //--------------------------------------------------------------------------- bool IoCmd::saveAll() { @@ -1614,7 +1622,7 @@ bool IoCmd::saveAll() { TApp *app = TApp::instance(); ToonzScene *scene = app->getCurrentScene()->getScene(); - + bool untitled = scene->isUntitled(); SceneResources resources(scene, 0); resources.save(scene->getScenePath()); resources.updatePaths(); @@ -1622,11 +1630,31 @@ bool IoCmd::saveAll() { // for update title bar app->getCurrentLevel()->notifyLevelTitleChange(); app->getCurrentPalette()->notifyPaletteTitleChanged(); - + if (untitled) scene->setUntitled(); return result; } //=========================================================================== +// IoCmd::saveNonSceneFiles() +//--------------------------------------------------------------------------- + +void IoCmd::saveNonSceneFiles() { + // try to save non scene files + + TApp *app = TApp::instance(); + ToonzScene *scene = app->getCurrentScene()->getScene(); + bool untitled = scene->isUntitled(); + SceneResources resources(scene, 0); + resources.save(scene->getScenePath()); + if (untitled) scene->setUntitled(); + resources.updatePaths(); + + // for update title bar + app->getCurrentLevel()->notifyLevelTitleChange(); + app->getCurrentPalette()->notifyPaletteTitleChanged(); +} + +//=========================================================================== // IoCmd::saveSound(soundPath, soundColumn, overwrite) //--------------------------------------------------------------------------- @@ -2738,3 +2766,12 @@ public: SaveAllCommandHandler() : MenuItemHandler(MI_SaveAll) {} void execute() override { IoCmd::saveAll(); } } saveAllCommandHandler; + +//============================================================================= +// Save all levels +//----------------------------------------------------------------------------- +class SaveAllLevelsCommandHandler : public MenuItemHandler { +public: + SaveAllLevelsCommandHandler() : MenuItemHandler(MI_SaveAllLevels) {} + void execute() { IoCmd::saveNonSceneFiles(); } +} saveAllLevelsCommandHandler; diff --git a/toonz/sources/toonz/iocommand.h b/toonz/sources/toonz/iocommand.h index 17f6fdb..2415e85 100644 --- a/toonz/sources/toonz/iocommand.h +++ b/toonz/sources/toonz/iocommand.h @@ -197,6 +197,8 @@ bool saveLevel(TXshSimpleLevel *sl); bool saveAll(); +void saveNonSceneFiles(); + bool saveSound(const TFilePath &fp, TXshSoundLevel *sc, bool overwrite); bool saveSound(TXshSoundLevel *sc); diff --git a/toonz/sources/toonz/locatorpopup.cpp b/toonz/sources/toonz/locatorpopup.cpp new file mode 100644 index 0000000..434ca52 --- /dev/null +++ b/toonz/sources/toonz/locatorpopup.cpp @@ -0,0 +1,117 @@ +#include "locatorpopup.h" + +// TnzLib includes +#include "toonz/txshlevelhandle.h" +#include "toonz/tframehandle.h" +#include "toonz/preferences.h" +#include "toonz/stage2.h" + +// Tnz6 includes +#include "tapp.h" +#include "sceneviewer.h" + +#include + +LocatorPopup::LocatorPopup(QWidget *parent) + : QDialog(parent), m_initialZoom(true) { + m_viewer = new SceneViewer(NULL); + m_viewer->setParent(parent); + m_viewer->setIsLocator(); + + //---- layout + QVBoxLayout *mainLayout = new QVBoxLayout(); + mainLayout->setMargin(0); + mainLayout->addWidget(m_viewer, 1); + setLayout(mainLayout); + + bool ret = true; + // When zoom changed, change window title. + ret = connect(m_viewer, SIGNAL(onZoomChanged()), SLOT(changeWindowTitle())); + ret = ret && + connect(m_viewer, SIGNAL(previewToggled()), SLOT(changeWindowTitle())); + assert(ret); + + resize(400, 400); +} + +//----------------------------------------------------------------------------- + +void LocatorPopup::onChangeViewAff(const TPointD &pos) { + TAffine curAff = m_viewer->getSceneMatrix(); + TAffine newAff(curAff.a11, 0, -pos.x * curAff.a11, 0, curAff.a22, + -pos.y * curAff.a22); + m_viewer->setViewMatrix(newAff, 0); + m_viewer->setViewMatrix(newAff, 1); + m_viewer->update(); +} + +//----------------------------------------------------------------------------- + +void LocatorPopup::showEvent(QShowEvent *) { + // zoom the locator for the first time + if (m_initialZoom) { + for (int z = 0; z < 4; z++) m_viewer->zoomQt(true, false); + m_initialZoom = false; + } + + TApp *app = TApp::instance(); + TFrameHandle *frameHandle = app->getCurrentFrame(); + TXshLevelHandle *levelHandle = app->getCurrentLevel(); + + bool ret = true; + ret = ret && connect(frameHandle, SIGNAL(frameSwitched()), this, + SLOT(changeWindowTitle())); + ret = ret && connect(levelHandle, SIGNAL(xshLevelSwitched(TXshLevel *)), this, + SLOT(changeWindowTitle())); + assert(ret); + + changeWindowTitle(); +} + +//----------------------------------------------------------------------------- + +void LocatorPopup::hideEvent(QHideEvent *) { + TApp *app = TApp::instance(); + disconnect(app->getCurrentLevel()); + disconnect(app->getCurrentFrame()); +} + +//----------------------------------------------------------------------------- + +void LocatorPopup::changeWindowTitle() { + TApp *app = TApp::instance(); + // put the titlebar texts in this string + QString name = tr("Locator"); + + bool showZoomFactor = false; + + // if the frame type is "scene editing" + if (app->getCurrentFrame()->isEditingScene()) { + if (m_viewer->isPreviewEnabled()) showZoomFactor = true; + + // If the current level exists and some option is set in the preference, + // set the zoom value to the current level's dpi + else if (Preferences::instance() + ->isActualPixelViewOnSceneEditingModeEnabled() && + app->getCurrentLevel()->getSimpleLevel() && + !CleanupPreviewCheck::instance() + ->isEnabled() // cleanup preview must be OFF + && + !CameraTestCheck::instance() + ->isEnabled()) // camera test mode must be OFF neither + showZoomFactor = true; + } + // if the frame type is "level editing" + else { + TXshLevel *level = app->getCurrentLevel()->getLevel(); + if (level) showZoomFactor = true; + } + + if (showZoomFactor) { + name = name + " Zoom : " + + QString::number((int)(100.0 * sqrt(m_viewer->getViewMatrix().det()) * + m_viewer->getDpiFactor())) + + "%"; + } + setWindowTitle(name); +} \ No newline at end of file diff --git a/toonz/sources/toonz/locatorpopup.h b/toonz/sources/toonz/locatorpopup.h new file mode 100644 index 0000000..2dc3448 --- /dev/null +++ b/toonz/sources/toonz/locatorpopup.h @@ -0,0 +1,34 @@ +#pragma once + +#ifndef LOCATORPOPUP_H +#define LOCATORPOPUP_H + +#include "tgeometry.h" +#include + +class SceneViewer; + +//============================================================================= +// LoactorPopup +//----------------------------------------------------------------------------- + +class LocatorPopup : public QDialog { + Q_OBJECT + SceneViewer* m_viewer; + bool m_initialZoom; + +public: + LocatorPopup(QWidget* parent = 0); + SceneViewer* viewer() { return m_viewer; } + + void onChangeViewAff(const TPointD& curPos); + +protected: + void showEvent(QShowEvent*); + void hideEvent(QHideEvent*); + +protected slots: + void changeWindowTitle(); +}; + +#endif \ No newline at end of file diff --git a/toonz/sources/toonz/magpiefileimportpopup.cpp b/toonz/sources/toonz/magpiefileimportpopup.cpp index 5134d72..72a90ab 100644 --- a/toonz/sources/toonz/magpiefileimportpopup.cpp +++ b/toonz/sources/toonz/magpiefileimportpopup.cpp @@ -124,7 +124,7 @@ MagpieFileImportPopup::MagpieFileImportPopup() FlipConsole::eRed | FlipConsole::eGreen | FlipConsole::eBlue | FlipConsole::eMatte | FlipConsole::eDefineSubCamera | FlipConsole::eDefineLoadBox | FlipConsole::eUseLoadBox | - FlipConsole::eFilledRaster)); + FlipConsole::eFilledRaster | FlipConsole::eLocator)); m_flipbook = new FlipBook(this, tr("Import Magpie File"), buttonMask); m_flipbook->setFixedHeight(250); frameLayout->addWidget(m_flipbook); diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index e0acfec..afca011 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -12,6 +12,7 @@ #include "iocommand.h" #include "tapp.h" #include "comboviewerpane.h" +#include "startuppopup.h" // TnzTools includes #include "tools/toolcommandids.h" @@ -1275,6 +1276,12 @@ void MainWindow::onMenuCheckboxChanged() { void MainWindow::showEvent(QShowEvent *event) { getCurrentRoom()->layout()->setEnabled(true); // See main function in // main.cpp + if (Preferences::instance()->isStartupPopupEnabled() && + !m_startupPopupShown) { + StartupPopup *startupPopup = new StartupPopup(); + startupPopup->show(); + m_startupPopupShown = true; + } } extern const char *applicationName; extern const char *applicationVersion; @@ -1558,9 +1565,9 @@ QAction *MainWindow::createToolAction(const char *id, const char *iconName, void MainWindow::defineActions() { createMenuFileAction(MI_NewScene, tr("&New Scene"), "Ctrl+N"); createMenuFileAction(MI_LoadScene, tr("&Load Scene..."), "Ctrl+L"); - createMenuFileAction(MI_SaveScene, tr("&Save Scene"), "Ctrl+S"); - createMenuFileAction(MI_SaveSceneAs, tr("&Save Scene As..."), "Ctrl+Shift+S"); - createMenuFileAction(MI_SaveAll, tr("&Save All"), ""); + createMenuFileAction(MI_SaveScene, tr("&Save Scene"), "Ctrl+Shift+S"); + createMenuFileAction(MI_SaveSceneAs, tr("&Save Scene As..."), ""); + createMenuFileAction(MI_SaveAll, tr("&Save All"), "Ctrl+S"); createMenuFileAction(MI_RevertScene, tr("&Revert Scene"), ""); QAction *act = CommandManager::instance()->getAction(MI_RevertScene); @@ -1576,9 +1583,10 @@ void MainWindow::defineActions() { ""); createMenuFileAction(MI_ClearRecentLevel, tr("&Clear Recent level File List"), ""); - createMenuFileAction(MI_NewLevel, tr("&New Level..."), ""); + createMenuFileAction(MI_NewLevel, tr("&New Level..."), "Alt+N"); createMenuFileAction(MI_LoadLevel, tr("&Load Level..."), ""); createMenuFileAction(MI_SaveLevel, tr("&Save Level"), ""); + createMenuFileAction(MI_SaveAllLevels, tr("&Save All Levels"), ""); createMenuFileAction(MI_SaveLevelAs, tr("&Save Level As..."), ""); createMenuFileAction(MI_ExportLevel, tr("&Export Level..."), ""); createMenuFileAction(MI_ConvertFileWithInput, tr("&Convert File..."), ""); @@ -1590,9 +1598,9 @@ void MainWindow::defineActions() { createMenuFileAction(MI_ProjectSettings, tr("&Project Settings..."), ""); createMenuFileAction(MI_SaveDefaultSettings, tr("&Save Default Settings"), ""); - createMenuFileAction(MI_OutputSettings, tr("&Output Settings..."), ""); + createMenuFileAction(MI_OutputSettings, tr("&Output Settings..."), "Ctrl+O"); createMenuFileAction(MI_PreviewSettings, tr("&Preview Settings..."), ""); - createMenuFileAction(MI_Render, tr("&Render"), ""); + createMenuFileAction(MI_Render, tr("&Render"), "Ctrl+Shift+R"); createMenuFileAction(MI_Preview, tr("&Preview"), "Ctrl+R"); createRightClickMenuAction(MI_SavePreviewedFrames, tr("&Save Previewed Frames"), ""); @@ -1607,13 +1615,13 @@ void MainWindow::defineActions() { MI_FreezePreview, tr("Freeze Preview"), tr("Unfreeze Preview")); // createAction(MI_SavePreview, "&Save Preview", ""); createRightClickMenuAction(MI_SavePreset, tr("&Save As Preset"), ""); - createMenuFileAction(MI_Preferences, tr("&Preferences..."), ""); + createMenuFileAction(MI_Preferences, tr("&Preferences..."), "Ctrl+U"); createMenuFileAction(MI_ShortcutPopup, tr("&Configure Shortcuts..."), ""); createMenuFileAction(MI_PrintXsheet, tr("&Print Xsheet"), ""); createMenuFileAction("MI_RunScript", tr("Run Script..."), ""); createMenuFileAction("MI_OpenScriptConsole", tr("Open Script Console..."), ""); - createMenuFileAction(MI_Print, tr("&Print Current Frame..."), ""); + createMenuFileAction(MI_Print, tr("&Print Current Frame..."), "Ctrl+P"); createMenuFileAction(MI_Quit, tr("&Quit"), "Ctrl+Q"); #ifndef NDEBUG createMenuFileAction("MI_ReloadStyle", tr("Reload qss"), ""); @@ -1639,10 +1647,14 @@ void MainWindow::defineActions() { createRightClickMenuAction(MI_PasteNames, tr("Paste Name"), ""); createRightClickMenuAction(MI_GetColorFromStudioPalette, tr("Get Color from Studio Palette"), ""); + createRightClickMenuAction(MI_ToggleLinkToStudioPalette, + tr("Toggle Link to Studio Palette"), ""); + createRightClickMenuAction(MI_RemoveReferenceToStudioPalette, + tr("Remove Reference to Studio Palette"), ""); createMenuEditAction(MI_Clear, tr("&Delete"), "Delete"); createMenuEditAction(MI_Insert, tr("&Insert"), "Ins"); createMenuEditAction(MI_Group, tr("&Group"), "Ctrl+G"); - createMenuEditAction(MI_Ungroup, tr("&Ungroup"), ""); + createMenuEditAction(MI_Ungroup, tr("&Ungroup"), "Ctrl+Shift+G"); createMenuEditAction(MI_BringToFront, tr("&Bring to Front"), "Ctrl+]"); createMenuEditAction(MI_BringForward, tr("&Bring Forward"), "]"); createMenuEditAction(MI_SendBack, tr("&Send Back"), "Ctrl+["); @@ -1747,8 +1759,8 @@ void MainWindow::defineActions() { createMenuCellsAction(MI_Increment, tr("&Autoexpose"), ""); createMenuCellsAction(MI_Dup, tr("&Repeat..."), ""); createMenuCellsAction(MI_ResetStep, tr("&Reset Step"), ""); - createMenuCellsAction(MI_IncreaseStep, tr("&Increase Step"), ""); - createMenuCellsAction(MI_DecreaseStep, tr("&Decrease Step"), ""); + createMenuCellsAction(MI_IncreaseStep, tr("&Increase Step"), "'"); + createMenuCellsAction(MI_DecreaseStep, tr("&Decrease Step"), ";"); createMenuCellsAction(MI_Step2, tr("&Step 2"), ""); createMenuCellsAction(MI_Step3, tr("&Step 3"), ""); createMenuCellsAction(MI_Step4, tr("&Step 4"), ""); @@ -1762,26 +1774,26 @@ void MainWindow::defineActions() { createMenuCellsAction(MI_Autorenumber, tr("&Autorenumber"), ""); createMenuCellsAction(MI_CloneLevel, tr("&Clone"), ""); createMenuCellsAction(MI_DrawingSubForward, - tr("Drawing Substitution Forward"), "."); + tr("Drawing Substitution Forward"), "W"); createMenuCellsAction(MI_DrawingSubBackward, - tr("Drawing Substitution Backward"), ","); + tr("Drawing Substitution Backward"), "Q"); createMenuCellsAction(MI_DrawingSubGroupForward, - tr("Similar Drawing Substitution Forward"), "Ctrl+."); + tr("Similar Drawing Substitution Forward"), "Alt+W"); createMenuCellsAction(MI_DrawingSubGroupBackward, - tr("Similar Drawing Substitution Backward"), "Ctrl+,"); + tr("Similar Drawing Substitution Backward"), "Alt+Q"); createMenuCellsAction(MI_Reframe1, tr("1's"), ""); createMenuCellsAction(MI_Reframe2, tr("2's"), ""); createMenuCellsAction(MI_Reframe3, tr("3's"), ""); createMenuCellsAction(MI_Reframe4, tr("4's"), ""); - createRightClickMenuAction(MI_SetKeyframes, tr("&Set Key"), ""); + createRightClickMenuAction(MI_SetKeyframes, tr("&Set Key"), "Z"); createToggle(MI_ViewCamera, tr("&Camera Box"), "", ViewCameraToggleAction ? 1 : 0, MenuViewCommandType); createToggle(MI_ViewTable, tr("&Table"), "", ViewTableToggleAction ? 1 : 0, MenuViewCommandType); - createToggle(MI_FieldGuide, tr("&Field Guide"), "", + createToggle(MI_FieldGuide, tr("&Field Guide"), "Shift+G", FieldGuideToggleAction ? 1 : 0, MenuViewCommandType); createToggle(MI_ViewBBox, tr("&Raster Bounding Box"), "", ViewBBoxToggleAction ? 1 : 0, MenuViewCommandType); @@ -1840,18 +1852,16 @@ void MainWindow::defineActions() { createToggle(MI_Link, tr("Link Flipbooks"), "", LinkToggleAction ? 1 : 0, MenuViewCommandType); - createPlaybackAction(MI_Play, tr("Play"), ""); - createPlaybackAction(MI_Loop, tr("Loop"), ""); + createPlaybackAction(MI_Play, tr("Play"), "P"); + createPlaybackAction(MI_Loop, tr("Loop"), "L"); createPlaybackAction(MI_Pause, tr("Pause"), ""); - createPlaybackAction(MI_FirstFrame, tr("First Frame"), ""); - createPlaybackAction(MI_LastFrame, tr("Last Frame"), ""); - createPlaybackAction(MI_PrevFrame, tr("Previous Frame"), "Shift+A"); - createPlaybackAction(MI_NextFrame, tr("Next Frame"), "Shift+S"); - - createAction(MI_NextDrawing, tr("Next Drawing"), "Shift+X", - PlaybackCommandType); - createAction(MI_PrevDrawing, tr("Prev Drawing"), "Shift+Z", - PlaybackCommandType); + createPlaybackAction(MI_FirstFrame, tr("First Frame"), "Alt+,"); + createPlaybackAction(MI_LastFrame, tr("Last Frame"), "Alt+."); + createPlaybackAction(MI_PrevFrame, tr("Previous Frame"), "Shift+,"); + createPlaybackAction(MI_NextFrame, tr("Next Frame"), "Shift+."); + + createAction(MI_NextDrawing, tr("Next Drawing"), ".", PlaybackCommandType); + createAction(MI_PrevDrawing, tr("Prev Drawing"), ",", PlaybackCommandType); createAction(MI_NextStep, tr("Next Step"), "", PlaybackCommandType); createAction(MI_PrevStep, tr("Prev Step"), "", PlaybackCommandType); @@ -1866,7 +1876,7 @@ void MainWindow::defineActions() { createViewerAction(MI_CompareToSnapshot, tr("Compare to Snapshot"), ""); createFillAction(MI_AutoFillToggle, - tr("Toggle Autofill on Current Palette Color"), ""); + tr("Toggle Autofill on Current Palette Color"), "Shift+A"); toggle = createToggle(MI_DockingCheck, tr("&Lock Room Panes"), "", @@ -1908,7 +1918,7 @@ void MainWindow::defineActions() { // createAction(MI_Export, "Export", "Ctrl+E"); createMenuWindowsAction(MI_OpenComboViewer, tr("&ComboViewer"), ""); - createMenuWindowsAction(MI_OpenHistoryPanel, tr("&History"), ""); + createMenuWindowsAction(MI_OpenHistoryPanel, tr("&History"), "Ctrl+H"); createMenuWindowsAction(MI_ResetRoomLayout, tr("&Reset to Default Rooms"), ""); @@ -1917,10 +1927,10 @@ void MainWindow::defineActions() { tr("Toggle Main Window's Full Screen Mode"), "Ctrl+`"); createMenuWindowsAction(MI_About, tr("&About OpenToonz..."), ""); - + createMenuWindowsAction(MI_StartupPopup, tr("&Startup Popup..."), "Alt+S"); createRightClickMenuAction(MI_BlendColors, tr("&Blend colors"), ""); - createToggle(MI_OnionSkin, tr("Onion Skin Toggle"), "//", false, + createToggle(MI_OnionSkin, tr("Onion Skin Toggle"), "/", false, RightClickMenuCommandType); createToggle(MI_ZeroThick, tr("Zero Thick Lines"), "Shift+/", false, RightClickMenuCommandType); @@ -1991,12 +2001,16 @@ void MainWindow::defineActions() { createRightClickMenuAction(MI_DisableAllColumns, tr("OFF All"), ""); createRightClickMenuAction(MI_DisableSelectedColumns, tr("OFF Selected"), ""); createRightClickMenuAction(MI_SwapEnabledColumns, tr("Swap ON/OFF"), ""); - createRightClickMenuAction(MI_LockThisColumnOnly, tr("Lock This Only"), ""); - createRightClickMenuAction(MI_LockSelectedColumns, tr("Lock Selected"), ""); - createRightClickMenuAction(MI_LockAllColumns, tr("Lock All"), ""); + createRightClickMenuAction(MI_LockThisColumnOnly, tr("Lock This Only"), + "Shift+L"); + createRightClickMenuAction(MI_LockSelectedColumns, tr("Lock Selected"), + "Ctrl+Shift+L"); + createRightClickMenuAction(MI_LockAllColumns, tr("Lock All"), + "Ctrl+Alt+Shift+L"); createRightClickMenuAction(MI_UnlockSelectedColumns, tr("Unlock Selected"), - ""); - createRightClickMenuAction(MI_UnlockAllColumns, tr("Unlock All"), ""); + "Ctrl+Shift+U"); + createRightClickMenuAction(MI_UnlockAllColumns, tr("Unlock All"), + "Ctrl+Alt+Shift+U"); createRightClickMenuAction(MI_ToggleColumnLocks, tr("Swap Lock/Unlock"), ""); /*-- カレントカラムの右側のカラムを全て非表示にするコマンド --*/ createRightClickMenuAction(MI_DeactivateUpperColumns, @@ -2012,31 +2026,32 @@ void MainWindow::defineActions() { createToolAction(T_Eraser, "eraser", tr("Eraser Tool"), "A"); createToolAction(T_Tape, "tape", tr("Tape Tool"), "T"); createToolAction(T_StylePicker, "stylepicker", tr("Style Picker Tool"), "K"); - createToolAction(T_RGBPicker, "RGBpicker", tr("RGB Picker Tool"), ""); + createToolAction(T_RGBPicker, "RGBpicker", tr("RGB Picker Tool"), "R"); createToolAction(T_ControlPointEditor, "controlpointeditor", tr("Control Point Editor Tool"), "C"); - createToolAction(T_Pinch, "pinch", tr("Pinch Tool"), "P"); + createToolAction(T_Pinch, "pinch", tr("Pinch Tool"), "M"); createToolAction(T_Pump, "pump", tr("Pump Tool"), ""); createToolAction(T_Magnet, "magnet", tr("Magnet Tool"), ""); createToolAction(T_Bender, "bender", tr("Bender Tool"), ""); createToolAction(T_Iron, "iron", tr("Iron Tool"), ""); createToolAction(T_Cutter, "cutter", tr("Cutter Tool"), ""); - createToolAction(T_Skeleton, "skeleton", tr("Skeleton Tool"), ""); + createToolAction(T_Skeleton, "skeleton", tr("Skeleton Tool"), "V"); createToolAction(T_Tracker, "tracker", tr("Tracker Tool"), ""); - createToolAction(T_Hook, "hook", tr("Hook Tool"), ""); + createToolAction(T_Hook, "hook", tr("Hook Tool"), "O"); createToolAction(T_Zoom, "zoom", tr("Zoom Tool"), "Shift+Space"); createToolAction(T_Rotate, "rotate", tr("Rotate Tool"), "Ctrl+Space"); createToolAction(T_Hand, "hand", tr("Hand Tool"), "Space"); - createToolAction(T_Plastic, "plastic", tr("Plastic Tool"), ""); + createToolAction(T_Plastic, "plastic", tr("Plastic Tool"), "X"); createToolAction(T_Ruler, "ruler", tr("Ruler Tool"), ""); createToolAction(T_Finger, "finger", tr("Finger Tool"), ""); createViewerAction(V_ZoomIn, tr("Zoom In"), "+"); createViewerAction(V_ZoomOut, tr("Zoom Out"), "-"); createViewerAction(V_ZoomReset, tr("Reset View"), "0"); - createViewerAction(V_ZoomFit, tr("Fit to Window"), ""); + createViewerAction(V_ZoomFit, tr("Fit to Window"), "9"); createViewerAction(V_ActualPixelSize, tr("Actual Pixel Size"), "N"); - createViewerAction(V_ShowHideFullScreen, tr("Show//Hide Full Screen"), ""); + createViewerAction(V_ShowHideFullScreen, tr("Show//Hide Full Screen"), + "Alt+F"); CommandManager::instance()->setToggleTexts(V_ShowHideFullScreen, tr("Full Screen Mode"), tr("Exit Full Screen Mode")); @@ -2046,13 +2061,13 @@ void MainWindow::defineActions() { createToolOptionsAction("A_ToolOption_GlobalKey", tr("Global Key"), ""); createToolOptionsAction("A_IncreaseMaxBrushThickness", - tr("Brush size - Increase max"), ""); + tr("Brush size - Increase max"), "I"); createToolOptionsAction("A_DecreaseMaxBrushThickness", - tr("Brush size - Decrease max"), ""); + tr("Brush size - Decrease max"), "U"); createToolOptionsAction("A_IncreaseMinBrushThickness", - tr("Brush size - Increase min"), ""); + tr("Brush size - Increase min"), "J"); createToolOptionsAction("A_DecreaseMinBrushThickness", - tr("Brush size - Decrease min"), ""); + tr("Brush size - Decrease min"), "H"); createToolOptionsAction("A_IncreaseBrushHardness", tr("Brush hardness - Increase"), ""); createToolOptionsAction("A_DecreaseBrushHardness", @@ -2071,7 +2086,7 @@ void MainWindow::defineActions() { createToolOptionsAction("A_ToolOption_PreserveThickness", tr("Preserve Thickness"), ""); createToolOptionsAction("A_ToolOption_PressureSensitivity", - tr("Pressure Sensitivity"), ""); + tr("Pressure Sensitivity"), "Shift+P"); createToolOptionsAction("A_ToolOption_SegmentInk", tr("Segment Ink"), "F8"); createToolOptionsAction("A_ToolOption_Selective", tr("Selective"), "F7"); createToolOptionsAction("A_ToolOption_Smooth", tr("Smooth"), ""); diff --git a/toonz/sources/toonz/mainwindow.h b/toonz/sources/toonz/mainwindow.h index 8efc118..4eb088a 100644 --- a/toonz/sources/toonz/mainwindow.h +++ b/toonz/sources/toonz/mainwindow.h @@ -67,6 +67,7 @@ class MainWindow final : public QMainWindow { Q_OBJECT bool m_saveSettingsOnQuit; + bool m_startupPopupShown = false; int m_oldRoomIndex; QString m_currentRoomsChoice; UpdateChecker *m_updateChecker; @@ -212,6 +213,7 @@ signals: }; class RecentFiles { + friend class StartupPopup; QList m_recentScenes; QList m_recentLevels; QList m_recentFlipbookImages; diff --git a/toonz/sources/toonz/menubar.cpp b/toonz/sources/toonz/menubar.cpp index 512c136..c578245 100644 --- a/toonz/sources/toonz/menubar.cpp +++ b/toonz/sources/toonz/menubar.cpp @@ -1077,6 +1077,7 @@ QMenuBar *StackedMenuBar::createFullMenuBar() { fileMenu->addSeparator(); addMenuItem(fileMenu, MI_NewLevel); addMenuItem(fileMenu, MI_LoadLevel); + addMenuItem(fileMenu, MI_SaveAllLevels); addMenuItem(fileMenu, MI_SaveLevel); addMenuItem(fileMenu, MI_SaveLevelAs); addMenuItem(fileMenu, MI_ExportLevel); @@ -1343,6 +1344,7 @@ QMenuBar *StackedMenuBar::createFullMenuBar() { //---Help Menu QMenu *helpMenu = addMenu(tr("Help"), fullMenuBar); + addMenuItem(helpMenu, MI_StartupPopup); addMenuItem(helpMenu, MI_About); return fullMenuBar; diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index ac9a5bf..6c79b5e 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -16,6 +16,7 @@ #define MI_SaveScene "MI_SaveScene" #define MI_SaveSceneAs "MI_SaveSceneAs" #define MI_SaveAll "MI_SaveAll" +#define MI_SaveAllLevels "MI_SaveAllLevels" #define MI_RevertScene "MI_RevertScene" #define MI_LoadSubSceneFile "MI_LoadSubSceneFile" @@ -310,5 +311,6 @@ #define MI_PreviewFx "MI_PreviewFx" #define MI_About "MI_About" +#define MI_StartupPopup "MI_StartupPopup" #define MI_PencilTest "MI_PencilTest" #endif diff --git a/toonz/sources/toonz/penciltestpopup.cpp b/toonz/sources/toonz/penciltestpopup.cpp index 4667d68..02fb1b2 100644 --- a/toonz/sources/toonz/penciltestpopup.cpp +++ b/toonz/sources/toonz/penciltestpopup.cpp @@ -33,6 +33,7 @@ // TnzCore includes #include "tsystem.h" #include "tpixelutils.h" +#include "tenv.h" #include @@ -64,9 +65,17 @@ #include #include #include +#include + +#ifdef _WIN32 +#include +#endif using namespace DVGui; +// Connected camera +TEnv::StringVar CamCapCameraName("CamCapCameraName", ""); + namespace { void convertImageToRaster(TRaster32P dstRas, const QImage& srcImg) { @@ -301,6 +310,90 @@ int letterToNum(QChar appendix) { return 0; } +#ifdef _WIN32 +void openCaptureFilterSettings(const QWidget* parent, + const QString& cameraName) { + HRESULT hr; + + ICreateDevEnum* createDevEnum = NULL; + IEnumMoniker* enumMoniker = NULL; + IMoniker* moniker = NULL; + + IBaseFilter* deviceFilter; + + ISpecifyPropertyPages* specifyPropertyPages; + CAUUID cauuid; + // set parent's window handle in order to make the dialog modal + HWND ghwndApp = (HWND)(parent->winId()); + + // initialize COM + CoInitialize(NULL); + + // get device list + CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, + IID_ICreateDevEnum, (PVOID*)&createDevEnum); + + // create EnumMoniker + createDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, + &enumMoniker, 0); + if (enumMoniker == NULL) { + // if no connected devices found + return; + } + + // reset EnumMoniker + enumMoniker->Reset(); + + // find target camera + ULONG fetched = 0; + bool isCameraFound = false; + while (hr = enumMoniker->Next(1, &moniker, &fetched), hr == S_OK) { + // get friendly name (= device name) of the camera + IPropertyBag* pPropertyBag; + moniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropertyBag); + VARIANT var; + var.vt = VT_BSTR; + VariantInit(&var); + + pPropertyBag->Read(L"FriendlyName", &var, 0); + + QString deviceName = QString::fromWCharArray(var.bstrVal); + + VariantClear(&var); + + if (deviceName == cameraName) { + // bind monkier to the filter + moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&deviceFilter); + + // release moniker etc. + moniker->Release(); + enumMoniker->Release(); + createDevEnum->Release(); + + isCameraFound = true; + break; + } + } + + // if no matching camera found + if (!isCameraFound) return; + + // open capture filter popup + hr = deviceFilter->QueryInterface(IID_ISpecifyPropertyPages, + (void**)&specifyPropertyPages); + if (hr == S_OK) { + hr = specifyPropertyPages->GetPages(&cauuid); + + hr = OleCreatePropertyFrame(ghwndApp, 30, 30, NULL, 1, + (IUnknown**)&deviceFilter, cauuid.cElems, + (GUID*)cauuid.pElems, 0, 0, NULL); + + CoTaskMemFree(cauuid.pElems); + specifyPropertyPages->Release(); + } +} +#endif + } // namespace //============================================================================= @@ -363,7 +456,7 @@ void MyViewFinder::paintEvent(QPaintEvent* event) { } } -void MyViewFinder::resizeEvent(QResizeEvent* event) { +void MyViewFinder::updateSize() { if (!m_camera) return; QSize cameraReso = m_camera->viewfinderSettings().resolution(); double cameraAR = (double)cameraReso.width() / (double)cameraReso.height(); @@ -381,6 +474,8 @@ void MyViewFinder::resizeEvent(QResizeEvent* event) { } } +void MyViewFinder::resizeEvent(QResizeEvent* event) { updateSize(); } + //============================================================================= FrameNumberLineEdit::FrameNumberLineEdit(QWidget* parent, int value) @@ -449,10 +544,34 @@ void FrameNumberLineEdit::focusOutEvent(QFocusEvent*) {} //============================================================================= +LevelNameLineEdit::LevelNameLineEdit(QWidget* parent) + : QLineEdit(parent), m_textOnFocusIn("") { + // Exclude all character which cannot fit in a filepath (Win). + // Dots are also prohibited since they are internally managed by Toonz. + QRegExp rx("[^\\\\/:?*.\"<>|]+"); + setValidator(new QRegExpValidator(rx, this)); + setObjectName("LargeSizedText"); + + connect(this, SIGNAL(editingFinished()), this, SLOT(onEditingFinished())); +} + +void LevelNameLineEdit::focusInEvent(QFocusEvent* e) { + m_textOnFocusIn = text(); +} + +void LevelNameLineEdit::onEditingFinished() { + // if the content is not changed, do nothing. + if (text() == m_textOnFocusIn) return; + + emit levelNameEdited(); +} + +//============================================================================= + PencilTestPopup::PencilTestPopup() : Dialog(TApp::instance()->getMainWindow(), false, false, "PencilTest") - , m_currentCamera(0) - , m_cameraImageCapture(0) + , m_currentCamera(NULL) + , m_cameraImageCapture(NULL) , m_captureWhiteBGCue(false) , m_captureCue(false) { setWindowTitle(tr("Camera Capture")); @@ -479,7 +598,7 @@ PencilTestPopup::PencilTestPopup() m_resolutionCombo = new QComboBox(this); QGroupBox* fileFrame = new QGroupBox(tr("File"), this); - m_levelNameEdit = new QLineEdit(this); + m_levelNameEdit = new LevelNameLineEdit(this); // set the start frame 10 if the option in preferences // "Show ABC Appendix to the Frame Number in Xsheet Cell" is active. // (frame 10 is displayed as "1" with this option) @@ -517,6 +636,12 @@ PencilTestPopup::PencilTestPopup() m_captureButton = new QPushButton(tr("Capture\n[Return key]"), this); QPushButton* closeButton = new QPushButton(tr("Close"), this); + +#ifdef _WIN32 + m_captureFilterSettingsBtn = new QPushButton(this); +#else + m_captureFilterSettingsBtn = 0; +#endif //---- m_resolutionCombo->setMaximumWidth(fontMetrics().width("0000 x 0000") + 25); @@ -524,11 +649,6 @@ PencilTestPopup::PencilTestPopup() m_fileTypeCombo->setCurrentIndex(0); fileFrame->setObjectName("CleanupSettingsFrame"); - // Exclude all character which cannot fit in a filepath (Win). - // Dots are also prohibited since they are internally managed by Toonz. - QRegExp rx("[^\\\\/:?*.\"<>|]+"); - m_levelNameEdit->setValidator(new QRegExpValidator(rx, this)); - m_levelNameEdit->setObjectName("LargeSizedText"); m_frameNumberEdit->setObjectName("LargeSizedText"); nextLevelButton->setFixedSize(24, 24); nextLevelButton->setArrowType(Qt::RightArrow); @@ -573,6 +693,14 @@ PencilTestPopup::PencilTestPopup() m_captureButton->setIcon(style.standardIcon(QStyle::SP_DialogOkButton)); m_captureButton->setIconSize(QSize(30, 30)); + if (m_captureFilterSettingsBtn) { + m_captureFilterSettingsBtn->setObjectName("GearButton"); + m_captureFilterSettingsBtn->setFixedSize(23, 23); + m_captureFilterSettingsBtn->setIconSize(QSize(15, 15)); + m_captureFilterSettingsBtn->setToolTip( + tr("Video Capture Filter Settings...")); + } + //---- layout ---- QHBoxLayout* mainLay = new QHBoxLayout(); mainLay->setMargin(0); @@ -592,6 +720,12 @@ PencilTestPopup::PencilTestPopup() camLay->addSpacing(10); camLay->addWidget(new QLabel(tr("Resolution:"), this), 0); camLay->addWidget(m_resolutionCombo, 1); + + if (m_captureFilterSettingsBtn) { + camLay->addSpacing(10); + camLay->addWidget(m_captureFilterSettingsBtn); + } + camLay->addStretch(0); } leftLay->addLayout(camLay, 0); @@ -739,6 +873,8 @@ PencilTestPopup::PencilTestPopup() this, SLOT(onResolutionComboActivated(const QString&))); ret = ret && connect(m_fileFormatOptionButton, SIGNAL(pressed()), this, SLOT(onFileFormatOptionButtonPressed())); + ret = ret && connect(m_levelNameEdit, SIGNAL(levelNameEdited()), this, + SLOT(onLevelNameEdited())); ret = ret && connect(nextLevelButton, SIGNAL(pressed()), this, SLOT(onNextName())); ret = ret && connect(m_colorTypeCombo, SIGNAL(currentIndexChanged(int)), this, @@ -761,17 +897,33 @@ PencilTestPopup::PencilTestPopup() ret = ret && connect(closeButton, SIGNAL(clicked()), this, SLOT(reject())); ret = ret && connect(m_captureButton, SIGNAL(clicked(bool)), this, SLOT(onCaptureButtonClicked(bool))); + if (m_captureFilterSettingsBtn) + ret = ret && connect(m_captureFilterSettingsBtn, SIGNAL(pressed()), this, + SLOT(onCaptureFilterSettingsBtnPressed())); assert(ret); refreshCameraList(); + + int startupCamIndex = m_cameraListCombo->findText( + QString::fromStdString(CamCapCameraName.getValue())); + if (startupCamIndex > 0) { + m_cameraListCombo->setCurrentIndex(startupCamIndex); + onCameraListComboActivated(startupCamIndex); + } + onNextName(); } //----------------------------------------------------------------------------- PencilTestPopup::~PencilTestPopup() { - if (m_currentCamera && m_currentCamera->state() == QCamera::ActiveState) - m_currentCamera->stop(); + if (m_currentCamera) { + if (m_currentCamera->state() == QCamera::ActiveState) + m_currentCamera->stop(); + if (m_currentCamera->state() == QCamera::LoadedState) + m_currentCamera->unload(); + delete m_currentCamera; + } // remove the cache image, if it exists TFilePath fp(m_cacheImagePath); if (TFileStatus(fp).doesExist()) TSystem::deleteFile(fp); @@ -790,27 +942,48 @@ void PencilTestPopup::refreshCameraList() { } int maxTextLength = 0; - int defaultIndex; + // add non-connected state as default + m_cameraListCombo->addItem(tr("- Select camera -")); for (int c = 0; c < cameras.size(); c++) { QString camDesc = cameras.at(c).description(); m_cameraListCombo->addItem(camDesc); maxTextLength = std::max(maxTextLength, fontMetrics().width(camDesc)); - if (cameras.at(c).deviceName() == QCameraInfo::defaultCamera().deviceName()) - defaultIndex = c; } m_cameraListCombo->setMaximumWidth(maxTextLength + 25); m_cameraListCombo->setEnabled(true); - m_cameraListCombo->setCurrentIndex(defaultIndex); - - onCameraListComboActivated(defaultIndex); + m_cameraListCombo->setCurrentIndex(0); } //----------------------------------------------------------------------------- -void PencilTestPopup::onCameraListComboActivated(int index) { +void PencilTestPopup::onCameraListComboActivated(int comboIndex) { QList cameras = QCameraInfo::availableCameras(); - if (cameras.size() != m_cameraListCombo->count()) return; + if (cameras.size() != m_cameraListCombo->count() - 1) return; + + // if selected the non-connected state, then disconnect the current camera + if (comboIndex == 0) { + m_cameraViewfinder->setCamera(NULL); + if (m_cameraImageCapture) { + disconnect(m_cameraImageCapture, + SIGNAL(imageCaptured(int, const QImage&)), this, + SLOT(onImageCaptured(int, const QImage&))); + delete m_cameraImageCapture; + m_cameraImageCapture = NULL; + } + if (m_currentCamera) { + if (m_currentCamera->state() == QCamera::ActiveState) + m_currentCamera->stop(); + if (m_currentCamera->state() == QCamera::LoadedState) + m_currentCamera->unload(); + } + m_deviceName = QString(); + m_cameraViewfinder->setImage(QImage()); + // update env + CamCapCameraName = ""; + return; + } + int index = comboIndex - 1; // in case the camera is not changed (just click the combobox) if (cameras.at(index).deviceName() == m_deviceName) return; @@ -850,11 +1023,13 @@ void PencilTestPopup::onCameraListComboActivated(int index) { settings.setResolution(sizes.last()); m_currentCamera->setViewfinderSettings(settings); QImageEncoderSettings imageEncoderSettings; - imageEncoderSettings.setCodec("PNG"); + imageEncoderSettings.setCodec("image/jpeg"); + imageEncoderSettings.setQuality(QMultimedia::NormalQuality); imageEncoderSettings.setResolution(sizes.last()); m_cameraImageCapture->setEncodingSettings(imageEncoderSettings); } m_cameraViewfinder->setCamera(m_currentCamera); + m_cameraViewfinder->updateSize(); // deleting old camera if (oldCamera) { @@ -864,6 +1039,9 @@ void PencilTestPopup::onCameraListComboActivated(int index) { // start new camera m_currentCamera->start(); m_cameraViewfinder->setImage(QImage()); + + // update env + CamCapCameraName = m_cameraListCombo->itemText(comboIndex).toStdString(); } //----------------------------------------------------------------------------- @@ -886,6 +1064,7 @@ void PencilTestPopup::onResolutionComboActivated(const QString& itemText) { imageEncoderSettings.setQuality(QMultimedia::NormalQuality); imageEncoderSettings.setResolution(newResolution); m_cameraImageCapture->setEncodingSettings(imageEncoderSettings); + m_cameraViewfinder->updateSize(); // reset white bg m_whiteBGImg = QImage(); @@ -909,6 +1088,17 @@ void PencilTestPopup::onFileFormatOptionButtonPressed() { //----------------------------------------------------------------------------- +void PencilTestPopup::onLevelNameEdited() { + // set the start frame 10 if the option in preferences + // "Show ABC Appendix to the Frame Number in Xsheet Cell" is active. + // (frame 10 is displayed as "1" with this option) + int startFrame = + Preferences::instance()->isShowFrameNumberWithLettersEnabled() ? 10 : 1; + m_frameNumberEdit->setValue(startFrame); +} + +//----------------------------------------------------------------------------- + void PencilTestPopup::onNextName() { const std::auto_ptr nameBuilder(NameBuilder::getBuilder(L"")); @@ -956,6 +1146,7 @@ void PencilTestPopup::onColorTypeComboChanged(int index) { //----------------------------------------------------------------------------- void PencilTestPopup::onImageCaptured(int id, const QImage& image) { + if (!m_cameraViewfinder) return; // capture the white BG if (m_captureWhiteBGCue) { m_whiteBGImg = image.copy(); @@ -1018,6 +1209,14 @@ void PencilTestPopup::showEvent(QShowEvent* event) { // then release the shortcut key temporary while the popup opens QAction* action = CommandManager::instance()->getActionFromShortcut("Return"); if (action) action->setShortcut(QKeySequence("")); + + // reload camera + if (m_currentCamera) { + if (m_currentCamera->state() == QCamera::UnloadedState) + m_currentCamera->load(); + if (m_currentCamera->state() == QCamera::LoadedState) + m_currentCamera->start(); + } } //----------------------------------------------------------------------------- @@ -1034,6 +1233,14 @@ void PencilTestPopup::hideEvent(QHideEvent* event) { m_captureButton->setChecked(false); onCaptureButtonClicked(false); } + + // release camera + if (m_currentCamera) { + if (m_currentCamera->state() == QCamera::ActiveState) + m_currentCamera->stop(); + if (m_currentCamera->state() == QCamera::LoadedState) + m_currentCamera->unload(); + } } //----------------------------------------------------------------------------- @@ -1213,7 +1420,7 @@ bool PencilTestPopup::importImage(QImage& image) { /* if the level does not exist in the scene cast */ else { /* if the file does exist, load it first */ - if (TFileStatus(actualLevelFp).doesExist()) { + if (TSystem::doesExistFileOrLevel(actualLevelFp)) { level = scene->loadLevel(actualLevelFp); if (!level) { error(tr("Failed to load %1.").arg(toQString(actualLevelFp))); @@ -1229,6 +1436,15 @@ bool PencilTestPopup::importImage(QImage& image) { "The captured image size does not match with the existing level.")); return false; } + + /* confirm overwrite */ + QString question = + tr("File %1 does exist.\nDo you want to overwrite it?") + .arg(toQString(actualLevelFp.withFrame(frameNumber))); + int ret = DVGui::MsgBox(question, QObject::tr("Overwrite"), + QObject::tr("Cancel")); + if (ret == 0 || ret == 2) return false; + } /* if the file does not exist, then create a new level */ else { @@ -1267,29 +1483,28 @@ bool PencilTestPopup::importImage(QImage& image) { int col = app->getCurrentColumn()->getColumnIndex(); /* try to find the vacant cell */ - int tmpRow = row; - bool isFoundEmptyCell = false; + int tmpRow = row; while (1) { - if (xsh->getCell(tmpRow, col).isEmpty()) { - isFoundEmptyCell = true; + /* if the same cell is already in the column, then just replace the content + * and do not set a new cell */ + if (xsh->getCell(tmpRow, col) == TXshCell(sl, fid)) break; + /* in case setting the same level as the the current column */ + else if (xsh->getCell(tmpRow, col).isEmpty()) { + xsh->setCell(tmpRow, col, TXshCell(sl, fid)); + break; + } + /* in case the level is different from the current column, then insert a new + column */ + else if (xsh->getCell(tmpRow, col).m_level->getSimpleLevel() != sl) { + col += 1; + xsh->insertColumn(col); + xsh->setCell(row, col, TXshCell(sl, fid)); + app->getCurrentColumn()->setColumnIndex(col); break; } - if (xsh->getCell(tmpRow, col).m_level->getSimpleLevel() != sl) break; tmpRow++; } - /* in case setting the same level as the the current column */ - if (isFoundEmptyCell) { - xsh->setCell(tmpRow, col, TXshCell(sl, fid)); - } - /* in case the level is different from the current column, then insert a new - column */ - else { - col += 1; - xsh->insertColumn(col); - xsh->setCell(row, col, TXshCell(sl, fid)); - app->getCurrentColumn()->setColumnIndex(col); - } /* notify */ app->getCurrentScene()->notifySceneChanged(); app->getCurrentScene()->notifyCastChange(); @@ -1300,4 +1515,20 @@ bool PencilTestPopup::importImage(QImage& image) { //----------------------------------------------------------------------------- +void PencilTestPopup::onCaptureFilterSettingsBtnPressed() { + if (!m_currentCamera || m_deviceName.isNull()) return; + + QList cameras = QCameraInfo::availableCameras(); + for (int c = 0; c < cameras.size(); c++) { + if (cameras.at(c).deviceName() == m_deviceName) { +#ifdef _WIN32 + openCaptureFilterSettings(this, cameras.at(c).description()); +#endif + return; + } + } +} + +//----------------------------------------------------------------------------- + OpenPopupCommandHandler openPencilTestPopup(MI_PencilTest); \ No newline at end of file diff --git a/toonz/sources/toonz/penciltestpopup.h b/toonz/sources/toonz/penciltestpopup.h index d2150ba..0ff31f4 100644 --- a/toonz/sources/toonz/penciltestpopup.h +++ b/toonz/sources/toonz/penciltestpopup.h @@ -21,6 +21,7 @@ class QVideoFrame; class QTimer; class QIntValidator; class QRegExpValidator; +class QPushButton; namespace DVGui { class FileField; @@ -61,6 +62,8 @@ public: repaint(); } + void updateSize(); + protected: void paintEvent(QPaintEvent* event); void resizeEvent(QResizeEvent* event); @@ -100,6 +103,25 @@ protected: }; //============================================================================= + +class LevelNameLineEdit : public QLineEdit { + Q_OBJECT + QString m_textOnFocusIn; + +public: + LevelNameLineEdit(QWidget* parent = 0); + +protected: + void focusInEvent(QFocusEvent* e); + +protected slots: + void onEditingFinished(); + +signals: + void levelNameEdited(); +}; + +//============================================================================= // PencilTestPopup //----------------------------------------------------------------------------- @@ -113,7 +135,7 @@ class PencilTestPopup : public DVGui::Dialog { QComboBox *m_cameraListCombo, *m_resolutionCombo, *m_fileTypeCombo, *m_colorTypeCombo; - QLineEdit* m_levelNameEdit; + LevelNameLineEdit* m_levelNameEdit; QCheckBox *m_upsideDownCB, *m_onionSkinCB, *m_saveOnCaptureCB, *m_timerCB; QPushButton *m_fileFormatOptionButton, *m_captureWhiteBGButton, *m_captureButton; @@ -126,6 +148,9 @@ class PencilTestPopup : public DVGui::Dialog { QImage m_whiteBGImg; + // used only for Windows + QPushButton* m_captureFilterSettingsBtn; + int m_timerId; QString m_cacheImagePath; bool m_captureWhiteBGCue; @@ -150,6 +175,7 @@ protected slots: void onCameraListComboActivated(int index); void onResolutionComboActivated(const QString&); void onFileFormatOptionButtonPressed(); + void onLevelNameEdited(); void onNextName(); void onColorTypeComboChanged(int index); void onImageCaptured(int, const QImage&); @@ -161,6 +187,7 @@ protected slots: void onCountDown(); void onCaptureButtonClicked(bool); + void onCaptureFilterSettingsBtnPressed(); }; #endif \ No newline at end of file diff --git a/toonz/sources/toonz/preferencespopup.cpp b/toonz/sources/toonz/preferencespopup.cpp index 1ee465b..d9d06f1 100644 --- a/toonz/sources/toonz/preferencespopup.cpp +++ b/toonz/sources/toonz/preferencespopup.cpp @@ -45,6 +45,7 @@ #include #include #include +#include using namespace DVGui; @@ -278,6 +279,33 @@ void PreferencesPopup::onPixelsOnlyChanged(int index) { //----------------------------------------------------------------------------- +void PreferencesPopup::onProjectRootChanged() { + int index = 0; + if (m_projectRootStuff->isChecked()) index |= 0x08; + if (m_projectRootDocuments->isChecked()) index |= 0x04; + if (m_projectRootDesktop->isChecked()) index |= 0x02; + if (m_projectRootCustom->isChecked()) index |= 0x01; + m_pref->setProjectRoot(index); + if (index & 0x01) { + m_customProjectRootFileField->show(); + m_customProjectRootLabel->show(); + m_projectRootDirections->show(); + } else { + m_customProjectRootFileField->hide(); + m_customProjectRootLabel->hide(); + m_projectRootDirections->hide(); + } +} + +//----------------------------------------------------------------------------- + +void PreferencesPopup::onCustomProjectRootChanged() { + QString text = m_customProjectRootFileField->getPath(); + m_pref->setCustomProjectRoot(text.toStdWString()); +} + +//----------------------------------------------------------------------------- + void PreferencesPopup::onPixelUnitExternallySelected(bool on) { // call slot function onPixelsOnlyChanged() accordingly m_pixelsOnlyCB->setCheckState((on) ? Qt::Checked : Qt::Unchecked); @@ -526,9 +554,37 @@ void PreferencesPopup::onDefaultViewerChanged(int index) { //----------------------------------------------------------------------------- -void PreferencesPopup::onAutoSaveChanged(int index) { - m_minuteFld->setEnabled(index == Qt::Checked); - m_pref->enableAutosave(index == Qt::Checked); +void PreferencesPopup::onAutoSaveChanged(bool on) { + m_pref->enableAutosave(on); + if (on && !m_autoSaveSceneCB->isChecked() && + !m_autoSaveOtherFilesCB->isChecked()) { + m_autoSaveSceneCB->setChecked(true); + m_autoSaveOtherFilesCB->setChecked(true); + } +} + +//----------------------------------------------------------------------------- + +void PreferencesPopup::onAutoSaveSceneChanged(int index) { + m_pref->enableAutosaveScene(index == Qt::Checked); + if (!m_autoSaveOtherFilesCB->isChecked() && index == Qt::Unchecked) { + m_autoSaveGroup->setChecked(false); + } +} + +//----------------------------------------------------------------------------- + +void PreferencesPopup::onAutoSaveOtherFilesChanged(int index) { + m_pref->enableAutosaveOtherFiles(index == Qt::Checked); + if (!m_autoSaveSceneCB->isChecked() && index == Qt::Unchecked) { + m_autoSaveGroup->setChecked(false); + } +} + +//----------------------------------------------------------------------------- + +void PreferencesPopup::onStartupPopupChanged(int index) { + m_pref->enableStartupPopup(index == Qt::Checked); } //----------------------------------------------------------------------------- @@ -939,8 +995,14 @@ PreferencesPopup::PreferencesPopup() new CheckBox(tr("Use Default Viewer for Movie Formats"), this); CheckBox *minimizeRasterMemoryCB = new CheckBox(tr("Minimize Raster Memory Fragmentation *"), this); - CheckBox *autoSaveCB = new CheckBox(tr("Save Automatically Every Minutes")); - m_minuteFld = new DVGui::IntLineEdit(this, 15, 1, 60); + m_autoSaveGroup = new QGroupBox(tr("Save Automatically"), this); + m_autoSaveGroup->setCheckable(true); + m_autoSaveSceneCB = new CheckBox(tr("Automatically Save the Scene File")); + m_autoSaveOtherFilesCB = + new CheckBox(tr("Automatically Save Non-Scene Files")); + CheckBox *startupPopupCB = + new CheckBox(tr("Show Startup Window when OpenToonz Starts")); + m_minuteFld = new DVGui::IntLineEdit(this, 15, 1, 60); CheckBox *replaceAfterSaveLevelAsCB = new CheckBox(tr("Replace Toonz Level after SaveLevelAs command"), this); @@ -952,6 +1014,15 @@ PreferencesPopup::PreferencesPopup() new DVGui::IntLineEdit(this, m_pref->getDefaultTaskChunkSize(), 1, 2000); CheckBox *sceneNumberingCB = new CheckBox(tr("Show Info in Rendered Frames")); + m_projectRootDocuments = new CheckBox(tr("My Documents/OpenToonz*"), this); + m_projectRootDesktop = new CheckBox(tr("Desktop/OpenToonz*"), this); + m_projectRootStuff = new CheckBox(tr("Stuff Folder*"), this); + m_projectRootCustom = new CheckBox(tr("Custom*"), this); + m_customProjectRootFileField = new DVGui::FileField(this, QString("")); + m_customProjectRootLabel = new QLabel(tr("Custom Project Path(s): ")); + m_projectRootDirections = new QLabel( + tr("Advanced: Multiple paths can be separated by ** (No Spaces)")); + QLabel *note_general = new QLabel(tr("* Changes will take effect the next time you run Toonz")); note_general->setStyleSheet("font-size: 10px; font: italic;"); @@ -1143,9 +1214,11 @@ PreferencesPopup::PreferencesPopup() //--- General ------------------------------ useDefaultViewerCB->setChecked(m_pref->isDefaultViewerEnabled()); minimizeRasterMemoryCB->setChecked(m_pref->isRasterOptimizedMemory()); - autoSaveCB->setChecked(m_pref->isAutosaveEnabled()); + m_autoSaveGroup->setChecked(m_pref->isAutosaveEnabled()); + m_autoSaveSceneCB->setChecked(m_pref->isAutosaveSceneEnabled()); + m_autoSaveOtherFilesCB->setChecked(m_pref->isAutosaveOtherFilesEnabled()); m_minuteFld->setValue(m_pref->getAutosavePeriod()); - m_minuteFld->setEnabled(m_pref->isAutosaveEnabled()); + startupPopupCB->setChecked(m_pref->isStartupPopupEnabled()); replaceAfterSaveLevelAsCB->setChecked( m_pref->isReplaceAfterSaveLevelAsEnabled()); @@ -1156,6 +1229,20 @@ PreferencesPopup::PreferencesPopup() m_levelsBackup->setChecked(m_pref->isLevelsBackupEnabled()); sceneNumberingCB->setChecked(m_pref->isSceneNumberingEnabled()); + m_customProjectRootFileField->setPath(m_pref->getCustomProjectRoot()); + + int projectPaths = m_pref->getProjectRoot(); + m_projectRootStuff->setChecked(projectPaths & 0x08); + m_projectRootDocuments->setChecked(projectPaths & 0x04); + m_projectRootDesktop->setChecked(projectPaths & 0x02); + m_projectRootCustom->setChecked(projectPaths & 0x01); + + m_projectRootStuff->hide(); + if (!(projectPaths & 0x01)) { + m_customProjectRootFileField->hide(); + m_customProjectRootLabel->hide(); + m_projectRootDirections->hide(); + } //--- Interface ------------------------------ QStringList styleSheetList; for (int i = 0; i < m_pref->getStyleSheetCount(); i++) { @@ -1378,16 +1465,29 @@ PreferencesPopup::PreferencesPopup() Qt::AlignLeft | Qt::AlignVCenter); generalFrameLay->addWidget(minimizeRasterMemoryCB, 0, Qt::AlignLeft | Qt::AlignVCenter); - QHBoxLayout *saveAutoLay = new QHBoxLayout(); - saveAutoLay->setMargin(0); - saveAutoLay->setSpacing(15); + + QVBoxLayout *autoSaveOptionsLay = new QVBoxLayout(); + autoSaveOptionsLay->setMargin(10); { - saveAutoLay->addWidget(autoSaveCB, 0); - saveAutoLay->addWidget(m_minuteFld, 0); - saveAutoLay->addStretch(1); - } - generalFrameLay->addLayout(saveAutoLay, 0); + QHBoxLayout *saveAutoLay = new QHBoxLayout(); + saveAutoLay->setMargin(0); + saveAutoLay->setSpacing(5); + { + saveAutoLay->addWidget(new QLabel(tr("Interval(Minutes): "), this)); + saveAutoLay->addWidget(m_minuteFld, 0); + saveAutoLay->addStretch(1); + } + autoSaveOptionsLay->addLayout(saveAutoLay, 0); + autoSaveOptionsLay->addWidget(m_autoSaveSceneCB, 0, + Qt::AlignLeft | Qt::AlignVCenter); + autoSaveOptionsLay->addWidget(m_autoSaveOtherFilesCB, 0, + Qt::AlignLeft | Qt::AlignVCenter); + } + m_autoSaveGroup->setLayout(autoSaveOptionsLay); + generalFrameLay->addWidget(m_autoSaveGroup); + generalFrameLay->addWidget(startupPopupCB, 0, + Qt::AlignLeft | Qt::AlignVCenter); // Unit, CameraUnit QGridLayout *unitLay = new QGridLayout(); unitLay->setMargin(0); @@ -1414,6 +1514,24 @@ PreferencesPopup::PreferencesPopup() Qt::AlignLeft | Qt::AlignVCenter); generalFrameLay->addWidget(sceneNumberingCB, 0, Qt::AlignLeft | Qt::AlignVCenter); + QGroupBox *projectGroupBox = + new QGroupBox(tr("Additional Project Locations"), this); + QGridLayout *projectRootLay = new QGridLayout(); + projectRootLay->setMargin(10); + projectRootLay->setHorizontalSpacing(5); + projectRootLay->setVerticalSpacing(10); + { + projectRootLay->addWidget(m_projectRootStuff, 0, 0); + projectRootLay->addWidget(m_projectRootDocuments, 1, 0); + projectRootLay->addWidget(m_projectRootDesktop, 2, 0); + projectRootLay->addWidget(m_projectRootCustom, 3, 0); + projectRootLay->addWidget(m_customProjectRootLabel, 4, 0, + Qt::AlignRight | Qt::AlignVCenter); + projectRootLay->addWidget(m_customProjectRootFileField, 4, 1, 1, 3); + projectRootLay->addWidget(m_projectRootDirections, 5, 0, 1, 4); + } + projectGroupBox->setLayout(projectRootLay); + generalFrameLay->addWidget(projectGroupBox, 0); generalFrameLay->addStretch(1); generalFrameLay->addWidget(note_general, 0); @@ -1882,10 +2000,16 @@ PreferencesPopup::PreferencesPopup() SLOT(onDefaultViewerChanged(int))); ret = ret && connect(minimizeRasterMemoryCB, SIGNAL(stateChanged(int)), this, SLOT(onRasterOptimizedMemoryChanged(int))); - ret = ret && connect(autoSaveCB, SIGNAL(stateChanged(int)), - SLOT(onAutoSaveChanged(int))); + ret = ret && connect(m_autoSaveGroup, SIGNAL(toggled(bool)), + SLOT(onAutoSaveChanged(bool))); + ret = ret && connect(m_autoSaveSceneCB, SIGNAL(stateChanged(int)), + SLOT(onAutoSaveSceneChanged(int))); + ret = ret && connect(m_autoSaveOtherFilesCB, SIGNAL(stateChanged(int)), + SLOT(onAutoSaveOtherFilesChanged(int))); ret = ret && connect(m_minuteFld, SIGNAL(editingFinished()), SLOT(onMinuteChanged())); + ret = ret && connect(startupPopupCB, SIGNAL(stateChanged(int)), + SLOT(onStartupPopupChanged(int))); ret = ret && connect(m_cellsDragBehaviour, SIGNAL(currentIndexChanged(int)), SLOT(onDragCellsBehaviourChanged(int))); ret = ret && connect(m_undoMemorySize, SIGNAL(editingFinished()), @@ -1896,7 +2020,16 @@ PreferencesPopup::PreferencesPopup() SLOT(onSceneNumberingChanged(int))); ret = ret && connect(m_chunkSizeFld, SIGNAL(editingFinished()), this, SLOT(onChunkSizeChanged())); - + ret = ret && connect(m_customProjectRootFileField, SIGNAL(pathChanged()), + this, SLOT(onCustomProjectRootChanged())); + ret = ret && connect(m_projectRootDocuments, SIGNAL(stateChanged(int)), + SLOT(onProjectRootChanged())); + ret = ret && connect(m_projectRootDesktop, SIGNAL(stateChanged(int)), + SLOT(onProjectRootChanged())); + ret = ret && connect(m_projectRootStuff, SIGNAL(stateChanged(int)), + SLOT(onProjectRootChanged())); + ret = ret && connect(m_projectRootCustom, SIGNAL(stateChanged(int)), + SLOT(onProjectRootChanged())); //--- Interface ---------------------- ret = ret && connect(styleSheetType, SIGNAL(currentIndexChanged(int)), SLOT(onStyleSheetTypeChanged(int))); diff --git a/toonz/sources/toonz/preferencespopup.h b/toonz/sources/toonz/preferencespopup.h index 616582a..ba790d7 100644 --- a/toonz/sources/toonz/preferencespopup.h +++ b/toonz/sources/toonz/preferencespopup.h @@ -24,6 +24,7 @@ class QLineEdit; class QPushButton; class QLabel; +class QGroupBox; //============================================================== @@ -58,7 +59,7 @@ private: DVGui::DoubleLineEdit *m_defLevelDpi; - QLabel *m_dpiLabel; + QLabel *m_dpiLabel, *m_customProjectRootLabel, *m_projectRootDirections; DVGui::IntLineEdit *m_minuteFld, *m_chunkSizeFld, *m_iconSizeLx, *m_iconSizeLy, *m_viewShrink, *m_viewStep, *m_blanksCount, @@ -68,11 +69,17 @@ private: QPushButton *m_addLevelFormat, *m_removeLevelFormat, *m_editLevelFormat; DVGui::CheckBox *m_inksOnly, *m_enableVersionControl, *m_levelsBackup, - *m_onionSkinVisibility, *m_pixelsOnlyCB, *m_onionSkinDuringPlayback, + *m_onionSkinVisibility, *m_pixelsOnlyCB, *m_projectRootDocuments, + *m_projectRootDesktop, *m_projectRootCustom, *m_projectRootStuff, + *m_onionSkinDuringPlayback, *m_autoSaveSceneCB, *m_autoSaveOtherFilesCB, *m_useNumpadForSwitchingStyles; + DVGui::FileField *m_customProjectRootFileField; + DVGui::FileField *m_ffmpegPathFileFld; + QGroupBox *m_autoSaveGroup; + private: // QWidget* create(const QString& lbl, bool def, const char* slot); void rebuildFormatsList(); @@ -80,6 +87,8 @@ private: private slots: void onPixelsOnlyChanged(int index); + void onProjectRootChanged(); + void onCustomProjectRootChanged(); void onPixelUnitExternallySelected(bool on); void onUnitChanged(int index); void onCameraUnitChanged(int index); @@ -99,7 +108,10 @@ private slots: void onRasterOptimizedMemoryChanged(int index); void onSaveUnpaintedInCleanupChanged(int index); void onMinimizeSaveboxAfterEditing(int index); - void onAutoSaveChanged(int index); + void onAutoSaveChanged(bool on); + void onAutoSaveSceneChanged(int index); + void onAutoSaveOtherFilesChanged(int index); + void onStartupPopupChanged(int index); void onDefaultViewerChanged(int index); void onBlankCountChanged(); void onBlankColorChanged(const TPixel32 &, bool isDragging); diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp index d039b34..1b521a2 100644 --- a/toonz/sources/toonz/sceneviewer.cpp +++ b/toonz/sources/toonz/sceneviewer.cpp @@ -10,6 +10,7 @@ #include "viewerdraw.h" #include "menubarcommandids.h" #include "ruler.h" +#include "locatorpopup.h" // TnzTools includes #include "tools/cursors.h" @@ -501,9 +502,9 @@ SceneViewer::SceneViewer(ImageUtils::FullScreenWidget *parent) , m_sideRasterPos() , m_topRasterPos() , m_toolDisableReason("") - , m_editPreviewSubCamera(false) { - assert(parent); - + , m_editPreviewSubCamera(false) + , m_locator(NULL) + , m_isLocator(false) { m_visualSettings.m_sceneProperties = TApp::instance()->getCurrentScene()->getScene()->getProperties(); // Enables multiple key input. @@ -880,6 +881,9 @@ void SceneViewer::hideEvent(QHideEvent *) { ToolHandle *toolHandle = app->getCurrentTool(); if (toolHandle) toolHandle->disconnect(this); + + // hide locator + if (m_locator && m_locator->isVisible()) m_locator->hide(); } //----------------------------------------------------------------------------- @@ -967,7 +971,7 @@ void SceneViewer::drawBuildVars() { } TTool *tool = app->getCurrentTool()->getTool(); - if (tool) tool->setViewer(this); + if (tool && !m_isLocator) tool->setViewer(this); } //----------------------------------------------------------------------------- @@ -1100,7 +1104,7 @@ void SceneViewer::drawCameraStand() { // Show white background when level editing mode. TTool *tool = TApp::instance()->getCurrentTool()->getTool(); if (m_drawEditingLevel && tool && tool->isEnabled()) { - tool->setViewer(this); + if (!m_isLocator) tool->setViewer(this); glPushMatrix(); if (m_referenceMode == CAMERA3D_REFERENCE) { mult3DMatrix(); @@ -1358,6 +1362,13 @@ void SceneViewer::drawOverlay() { // use // another glContext if (tool->getName() == "T_RGBPicker") tool->onImageChanged(); + + // draw cross at the center of the locator window + if (m_isLocator) { + glColor3d(1.0, 0.0, 0.0); + tglDrawSegment(TPointD(-4, 0), TPointD(5, 0)); + tglDrawSegment(TPointD(0, -4), TPointD(0, 5)); + } } } diff --git a/toonz/sources/toonz/sceneviewer.h b/toonz/sources/toonz/sceneviewer.h index 68ed8de..0941505 100644 --- a/toonz/sources/toonz/sceneviewer.h +++ b/toonz/sources/toonz/sceneviewer.h @@ -33,6 +33,7 @@ class Ruler; class QMenu; class SceneViewer; +class LocatorPopup; namespace ImageUtils { class FullScreenWidget; @@ -135,6 +136,9 @@ class SceneViewer final : public QGLWidget, TOP_3D, } m_current3DDevice; + LocatorPopup *m_locator; + bool m_isLocator; + // iwsw commented out temporarily // Ghibli3DLutUtil * m_ghibli3DLutUtil; public: @@ -230,6 +234,8 @@ public: void setFocus(Qt::FocusReason reason) { QWidget::setFocus(reason); }; + void setIsLocator() { m_isLocator = true; } + public: // SceneViewer's gadget public functions TPointD winToWorld(const QPoint &pos) const; diff --git a/toonz/sources/toonz/sceneviewerevents.cpp b/toonz/sources/toonz/sceneviewerevents.cpp index c55a75a..201a553 100644 --- a/toonz/sources/toonz/sceneviewerevents.cpp +++ b/toonz/sources/toonz/sceneviewerevents.cpp @@ -14,6 +14,7 @@ #include "onionskinmaskgui.h" #include "ruler.h" #include "comboviewerpane.h" +#include "locatorpopup.h" // TnzQt includes #include "toonzqt/tselectionhandle.h" @@ -184,6 +185,14 @@ void SceneViewer::onButtonPressed(FlipConsole::EGadget button) { m_editPreviewSubCamera = !m_editPreviewSubCamera; update(); break; + + // open locator. Create one for the first time + case FlipConsole::eLocator: + if (!m_locator) m_locator = new LocatorPopup(this); + m_locator->show(); + m_locator->raise(); + m_locator->activateWindow(); + break; } } @@ -351,7 +360,12 @@ void SceneViewer::mouseMoveEvent(QMouseEvent *event) { TMouseEvent toonzEvent; initToonzEvent(toonzEvent, event, height(), m_pressure, m_tabletEvent, false); - TPointD pos = tool->getMatrix().inv() * winToWorld(curPos); + TPointD worldPos = winToWorld(curPos); + TPointD pos = tool->getMatrix().inv() * worldPos; + + if (m_locator) { + m_locator->onChangeViewAff(worldPos); + } TObjectHandle *objHandle = TApp::instance()->getCurrentObject(); if (tool->getToolType() & TTool::LevelTool && !objHandle->isSpline()) { @@ -379,6 +393,7 @@ void SceneViewer::mouseMoveEvent(QMouseEvent *event) { // panning panQt(curPos - m_pos); m_pos = curPos; + return; } } @@ -1009,6 +1024,7 @@ void SceneViewer::contextMenuEvent(QContextMenuEvent *e) { #endif if (m_freezedStatus != NO_FREEZED) return; + if (m_isLocator) return; TPoint winPos(e->pos().x(), height() - e->pos().y()); std::vector columnIndices; diff --git a/toonz/sources/toonz/shortcutpopup.cpp b/toonz/sources/toonz/shortcutpopup.cpp index 5e36062..b51b020 100644 --- a/toonz/sources/toonz/shortcutpopup.cpp +++ b/toonz/sources/toonz/shortcutpopup.cpp @@ -5,8 +5,13 @@ // Tnz6 includes #include "menubarcommandids.h" #include "tapp.h" +#include "tenv.h" +#include "tsystem.h" +#include "toonz/preferences.h" +#include "toonz/toonzfolders.h" // TnzQt includes +#include "toonzqt/gutil.h" #include "toonzqt/menubarcommand.h" #include "toonzqt/dvdialog.h" @@ -27,6 +32,9 @@ #include #include #include +#include +#include +#include // STD includes #include @@ -166,7 +174,7 @@ void ShortcutViewer::keyPressEvent(QKeyEvent *event) { void ShortcutViewer::removeShortcut() { if (m_action) { - CommandManager::instance()->setShortcut(m_action, ""); + CommandManager::instance()->setShortcut(m_action, "", false); emit shortcutChanged(); update(); } @@ -350,14 +358,32 @@ void ShortcutTree::onShortcutChanged() { ShortcutPopup::ShortcutPopup() : Dialog(TApp::instance()->getMainWindow(), false, false, "Shortcut") { setWindowTitle(tr("Configure Shortcuts")); + m_presetChoiceCB = new QComboBox(this); + buildPresets(); + m_presetChoiceCB->setCurrentIndex(0); m_list = new ShortcutTree(this); m_list->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_list->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - m_sViewer = new ShortcutViewer(this); - m_removeBtn = new QPushButton(tr("Remove"), this); + m_sViewer = new ShortcutViewer(this); + m_removeBtn = new QPushButton(tr("Remove"), this); + m_loadShortcutsPopup = NULL; + m_saveShortcutsPopup = NULL; + m_dialog = NULL; + m_exportButton = new QPushButton(tr("Export Current Shortcuts"), this); + m_exportButton->setToolTip(tr("Export Current Shortcuts")); + m_deletePresetButton = new QPushButton("Delete", this); + m_deletePresetButton->setToolTip(tr("Delete Current Preset")); + m_deletePresetButton->setIcon(QIcon(":Resources/delete_on.png")); + m_savePresetButton = new QPushButton("Save As", this); + m_savePresetButton->setToolTip(tr("Save Current Shortcuts as New Preset")); + m_savePresetButton->setIcon(QIcon(":Resources/saveas_on.png")); + m_loadPresetButton = new QPushButton(tr("Apply")); + m_loadPresetButton->setToolTip(tr("Use selected preset as shortcuts")); + m_loadPresetButton->setIcon(QIcon(":Resources/green.png")); + m_clearAllShortcutsButton = new QPushButton(tr("Clear All Shortcuts")); QLabel *noSearchResultLabel = new QLabel(tr("Couldn't find any matching command."), this); noSearchResultLabel->setHidden(true); @@ -394,6 +420,28 @@ ShortcutPopup::ShortcutPopup() bottomLayout->addWidget(m_removeBtn, 0); } m_topLayout->addLayout(bottomLayout, 0); + m_topLayout->addSpacing(10); + QHBoxLayout *presetLay = new QHBoxLayout(); + presetLay->setMargin(0); + presetLay->setSpacing(5); + { + presetLay->addWidget(new QLabel("Preset:", this), 0); + presetLay->addWidget(m_presetChoiceCB, 1); + presetLay->addWidget(m_loadPresetButton, 0); + presetLay->addWidget(m_savePresetButton, 0); + presetLay->addWidget(m_deletePresetButton, 0); + } + m_topLayout->addLayout(presetLay, 0); + m_topLayout->addSpacing(10); + QHBoxLayout *exportLay = new QHBoxLayout(); + exportLay->setMargin(0); + exportLay->setSpacing(5); + { + exportLay->addWidget(m_exportButton, 0); + exportLay->addWidget(m_clearAllShortcutsButton, 0); + } + m_topLayout->addLayout(exportLay, 0); + // m_topLayout->addWidget(m_exportButton, 0); } connect(m_list, SIGNAL(actionSelected(QAction *)), m_sViewer, @@ -408,6 +456,14 @@ ShortcutPopup::ShortcutPopup() SLOT(setHidden(bool))); connect(searchEdit, SIGNAL(textChanged(const QString &)), this, SLOT(onSearchTextChanged(const QString &))); + connect(m_presetChoiceCB, SIGNAL(currentIndexChanged(int)), + SLOT(onPresetChanged(int))); + connect(m_exportButton, SIGNAL(clicked()), SLOT(onExportButton())); + connect(m_deletePresetButton, SIGNAL(clicked()), SLOT(onDeletePreset())); + connect(m_savePresetButton, SIGNAL(clicked()), SLOT(onSavePreset())); + connect(m_loadPresetButton, SIGNAL(clicked()), SLOT(onLoadPreset())); + connect(m_clearAllShortcutsButton, SIGNAL(clicked()), + SLOT(clearAllShortcuts())); } //----------------------------------------------------------------------------- @@ -426,4 +482,324 @@ void ShortcutPopup::onSearchTextChanged(const QString &text) { //----------------------------------------------------------------------------- +void ShortcutPopup::onPresetChanged(int index) { + if (m_presetChoiceCB->currentText() == "Load from file...") { + importPreset(); + } +} + +//----------------------------------------------------------------------------- + +void ShortcutPopup::clearAllShortcuts(bool warning) { + if (warning) { + QString question(tr("This will erase ALL shortcuts. Continue?")); + int ret = + DVGui::MsgBox(question, QObject::tr("OK"), QObject::tr("Cancel"), 0); + if (ret == 0 || ret == 2) { + // cancel (or closed message box window) + return; + } + showDialog("Clearing All Shortcuts"); + } + for (int commandType = UndefinedCommandType; commandType <= MenuCommandType; + commandType++) { + std::vector actions; + CommandManager::instance()->getActions((CommandType)commandType, actions); + for (QAction *action : actions) { + qApp->processEvents(); + m_sViewer->setAction(action); + m_sViewer->removeShortcut(); + } + } + setCurrentPresetPref("DELETED"); + // if warning is true, this was called directly- need to hide the dialog after + if (warning) m_dialog->hide(); +} + +//----------------------------------------------------------------------------- + +void ShortcutPopup::setPresetShortcuts(TFilePath fp) { + QSettings preset(toQString(fp), QSettings::IniFormat); + preset.beginGroup("shortcuts"); + QStringList allIds = preset.allKeys(); + QAction *action; + for (QString id : allIds) { + QByteArray ba = id.toLatin1(); + const char *charId = ba.data(); + action = CommandManager::instance()->getAction((CommandId)charId); + CommandManager::instance()->setShortcut( + action, preset.value(id).toString().toStdString(), false); + } + preset.endGroup(); + emit m_sViewer->shortcutChanged(); + m_dialog->hide(); + buildPresets(); + setCurrentPresetPref(QString::fromStdString(fp.getName())); +} + +//----------------------------------------------------------------------------- + +bool ShortcutPopup::showConfirmDialog() { + QString question(tr("This will overwrite all current shortcuts. Continue?")); + 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 + return true; +} + +//----------------------------------------------------------------------------- + +bool ShortcutPopup::showOverwriteDialog(QString name) { + QString question(tr("A file named ") + name + + tr(" already exists. Do you want to replace it?")); + int ret = DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"), 0); + if (ret == 0 || ret == 2) { + // cancel (or closed message box window) + return false; + } else + return true; +} + +//----------------------------------------------------------------------------- + +void ShortcutPopup::showDialog(QString text) { + if (m_dialog == NULL) { + m_dialogLabel = new QLabel("", this); + m_dialog = new DVGui::Dialog(this, false, false); + m_dialog->setWindowTitle(tr("OpenToonz - Setting Shortcuts")); + m_dialog->setModal(false); + + m_dialog->setTopMargin(10); + m_dialog->setTopSpacing(10); + m_dialog->setLabelWidth(500); + m_dialog->beginVLayout(); + m_dialog->addWidget(m_dialogLabel, false); + m_dialog->endVLayout(); + } + m_dialogLabel->setText(text); + m_dialog->show(); +} + +//----------------------------------------------------------------------------- + +void ShortcutPopup::onExportButton(TFilePath fp) { + if (fp == TFilePath()) { + m_saveShortcutsPopup = new GenericSaveFilePopup("Save Current Shortcuts"); + m_saveShortcutsPopup->addFilterType("ini"); + fp = m_saveShortcutsPopup->getPath(); + if (fp == TFilePath()) return; + } + showDialog("Saving Shortcuts"); + QString shortcutString = "[shortcuts]\n"; + for (int commandType = UndefinedCommandType; commandType <= MenuCommandType; + commandType++) { + std::vector actions; + CommandManager::instance()->getActions((CommandType)commandType, actions); + for (QAction *action : actions) { + qApp->processEvents(); + std::string id = CommandManager::instance()->getIdFromAction(action); + std::string shortcut = + CommandManager::instance()->getShortcutFromAction(action); + if (shortcut != "") { + shortcutString = shortcutString + QString::fromStdString(id) + "=" + + QString::fromStdString(shortcut) + "\n"; + } + } + } + QFile file(fp.getQString()); + file.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream out(&file); + out << shortcutString; + file.close(); + m_dialog->hide(); +} + +//----------------------------------------------------------------------------- + +void ShortcutPopup::onDeletePreset() { + // change this to 4 once RETAS shortcuts are updated + if (m_presetChoiceCB->currentIndex() <= 3) { + DVGui::MsgBox(DVGui::CRITICAL, tr("Included presets cannot be deleted.")); + return; + } + + QString question(tr("Are you sure you want to delete the preset: ") + + m_presetChoiceCB->currentText() + tr("?")); + int ret = DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"), 0); + if (ret == 0 || ret == 2) { + // cancel (or closed message box window) + return; + } + TFilePath presetDir = + ToonzFolder::getMyModuleDir() + TFilePath("shortcutpresets"); + QString presetName = m_presetChoiceCB->currentText(); + if (TSystem::doesExistFileOrLevel(presetDir + + TFilePath(presetName + ".ini"))) { + TSystem::deleteFile(presetDir + TFilePath(presetName + ".ini")); + buildPresets(); + m_presetChoiceCB->setCurrentIndex(0); + } + if (Preferences::instance()->getShortcutPreset() == presetName) + setCurrentPresetPref("DELETED"); + getCurrentPresetPref(); +} + +//----------------------------------------------------------------------------- + +void ShortcutPopup::importPreset() { + m_loadShortcutsPopup = new GenericLoadFilePopup("Load Shortcuts File"); + m_loadShortcutsPopup->addFilterType("ini"); + TFilePath shortcutPath = m_loadShortcutsPopup->getPath(); + if (shortcutPath == TFilePath()) { + m_presetChoiceCB->setCurrentIndex(0); + return; + } + if (!showConfirmDialog()) return; + + TFilePath presetDir = + ToonzFolder::getMyModuleDir() + TFilePath("shortcutpresets"); + if (!TSystem::doesExistFileOrLevel(presetDir)) { + TSystem::mkDir(presetDir); + } + QString name = shortcutPath.withoutParentDir().getQString(); + std::string strName = name.toStdString(); + if (TSystem::doesExistFileOrLevel(presetDir + TFilePath(name))) { + if (!showOverwriteDialog(name)) return; + } + showDialog("Importing Shortcuts"); + TSystem::copyFile(presetDir + TFilePath(name), shortcutPath, true); + clearAllShortcuts(false); + setPresetShortcuts(presetDir + TFilePath(name)); + return; +} + +//----------------------------------------------------------------------------- + +void ShortcutPopup::onLoadPreset() { + QString preset = m_presetChoiceCB->currentText(); + TFilePath presetDir = + ToonzFolder::getMyModuleDir() + TFilePath("shortcutpresets"); + TFilePath defaultPresetDir = + ToonzFolder::getProfileFolder() + TFilePath("layouts/shortcuts"); + if (preset == "") return; + if (preset == "Load from file...") { + importPreset(); + return; + } + + if (!showConfirmDialog()) return; + showDialog("Setting Shortcuts"); + if (preset == "OpenToonz") { + clearAllShortcuts(false); + TFilePath fp = defaultPresetDir + TFilePath("defopentoonz.ini"); + setPresetShortcuts(fp); + return; + } else if (preset == "Toon Boom Harmony") { + clearAllShortcuts(false); + TFilePath fp = defaultPresetDir + TFilePath("otharmony.ini"); + setPresetShortcuts(fp); + return; + } else if (preset == "Adobe Animate(Flash)") { + clearAllShortcuts(false); + TFilePath fp = defaultPresetDir + TFilePath("otadobe.ini"); + setPresetShortcuts(fp); + return; + } else if (preset == "RETAS PaintMan") { + clearAllShortcuts(false); + TFilePath fp = defaultPresetDir + TFilePath("otretas.ini"); + setPresetShortcuts(fp); + return; + } else if (TSystem::doesExistFileOrLevel(presetDir + + TFilePath(preset + ".ini"))) { + clearAllShortcuts(false); + TFilePath fp = presetDir + TFilePath(preset + ".ini"); + setPresetShortcuts(fp); + return; + } + m_dialog->hide(); +} + +//----------------------------------------------------------------------------- + +QStringList ShortcutPopup::buildPresets() { + QStringList presets; + presets << "" + << "OpenToonz" + //<< "RETAS PaintMan" + << "Toon Boom Harmony" + << "Adobe Animate(Flash)"; + TFilePath presetDir = + ToonzFolder::getMyModuleDir() + TFilePath("shortcutpresets"); + if (TSystem::doesExistFileOrLevel(presetDir)) { + TFilePathSet fps = TSystem::readDirectory(presetDir, true, true, false); + QStringList customPresets; + for (TFilePath fp : fps) { + if (fp.getType() == "ini") { + customPresets << QString::fromStdString(fp.getName()); + std::string name = fp.getName(); + } + } + customPresets.sort(); + presets = presets + customPresets; + } + presets << tr("Load from file..."); + m_presetChoiceCB->clear(); + m_presetChoiceCB->addItems(presets); + return presets; +} + +//----------------------------------------------------------------------------- + +void ShortcutPopup::onSavePreset() { + QString presetName = DVGui::getText("Enter Preset Name", "Preset Name:", ""); + if (presetName == "") return; + TFilePath presetDir = + ToonzFolder::getMyModuleDir() + TFilePath("shortcutpresets"); + if (!TSystem::doesExistFileOrLevel(presetDir)) { + TSystem::mkDir(presetDir); + } + TFilePath fp; + fp = presetDir + TFilePath(presetName + ".ini"); + if (TSystem::doesExistFileOrLevel(fp)) { + if (!showOverwriteDialog(QString::fromStdString(fp.getName()))) return; + } + onExportButton(fp); + + buildPresets(); + setCurrentPresetPref(presetName); +} + +//----------------------------------------------------------------------------- + +void ShortcutPopup::showEvent(QShowEvent *se) { getCurrentPresetPref(); } + +//----------------------------------------------------------------------------- + +void ShortcutPopup::setCurrentPresetPref(QString name) { + Preferences::instance()->setShortcutPreset(name.toStdString()); + getCurrentPresetPref(); +} + +//----------------------------------------------------------------------------- + +void ShortcutPopup::getCurrentPresetPref() { + QString name = Preferences::instance()->getShortcutPreset(); + if (name == "DELETED") + m_presetChoiceCB->setCurrentText(""); + else if (name == "defopentoonz") + m_presetChoiceCB->setCurrentText("OpenToonz"); + else if (name == "otharmony") + m_presetChoiceCB->setCurrentText("Toon Boom Harmony"); + else if (name == "otadobe") + m_presetChoiceCB->setCurrentText("Adobe Animate(Flash)"); + else if (name == "otretas") + m_presetChoiceCB->setCurrentText("RETAS PaintMan"); + + else + m_presetChoiceCB->setCurrentText(name); +} + OpenPopupCommandHandler openShortcutPopup(MI_ShortcutPopup); diff --git a/toonz/sources/toonz/shortcutpopup.h b/toonz/sources/toonz/shortcutpopup.h index 2044ac6..142d04f 100644 --- a/toonz/sources/toonz/shortcutpopup.h +++ b/toonz/sources/toonz/shortcutpopup.h @@ -5,7 +5,8 @@ #include #include - +#include +#include "filebrowserpopup.h" #include "toonzqt/dvdialog.h" // forward declaration @@ -92,13 +93,40 @@ class ShortcutPopup final : public DVGui::Dialog { QPushButton *m_removeBtn; ShortcutViewer *m_sViewer; ShortcutTree *m_list; + QComboBox *m_presetChoiceCB; + DVGui::Dialog *m_dialog; + GenericLoadFilePopup *m_loadShortcutsPopup; + GenericSaveFilePopup *m_saveShortcutsPopup; + QPushButton *m_exportButton; + QPushButton *m_deletePresetButton; + QPushButton *m_savePresetButton; + QPushButton *m_loadPresetButton; + QPushButton *m_clearAllShortcutsButton; + QLabel *m_dialogLabel; public: ShortcutPopup(); ~ShortcutPopup(); +private: + void setPresetShortcuts(TFilePath fp); + void showDialog(QString text); + bool showConfirmDialog(); + bool showOverwriteDialog(QString name); + void importPreset(); + QStringList buildPresets(); + void showEvent(QShowEvent *se) override; + void setCurrentPresetPref(QString preset); + void getCurrentPresetPref(); + protected slots: + void clearAllShortcuts(bool warning = true); void onSearchTextChanged(const QString &text); + void onPresetChanged(int index); + void onExportButton(TFilePath fp = TFilePath()); + void onDeletePreset(); + void onSavePreset(); + void onLoadPreset(); }; #endif // SHORTCUTPOPUP_H diff --git a/toonz/sources/toonz/startuppopup.cpp b/toonz/sources/toonz/startuppopup.cpp new file mode 100644 index 0000000..bf8c375 --- /dev/null +++ b/toonz/sources/toonz/startuppopup.cpp @@ -0,0 +1,917 @@ + + +#include "startuppopup.h" + +// Tnz6 includes +#include "mainwindow.h" +#include "tapp.h" +#include "iocommand.h" +#include "toutputproperties.h" +#include "toonzqt/flipconsole.h" +#include "menubarcommandids.h" +#include "tenv.h" +#include "toonz/stage.h" + +// TnzQt includes +#include "toonzqt/menubarcommand.h" +#include "toonzqt/gutil.h" +#include "toonzqt/doublefield.h" + +// TnzLib includes +#include "toonz/toonzscene.h" +#include "toonz/txsheet.h" +#include "toonz/levelproperties.h" +#include "toonz/sceneproperties.h" +#include "toonz/tcamera.h" +#include "toonz/tscenehandle.h" +#include "toonz/txsheethandle.h" +#include "toonz/preferences.h" +#include "toonz/tproject.h" + +// TnzCore includes +#include "tsystem.h" +#include "filebrowsermodel.h" + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace DVGui; + +namespace { + +// the first value in the preset list +const QString custom = QObject::tr(""); + +QString removeZeros(QString srcStr) { + if (!srcStr.contains('.')) return srcStr; + + for (int i = srcStr.length() - 1; i >= 0; i--) { + if (srcStr.at(i) == '0') + srcStr.chop(1); + else if (srcStr.at(i) == '.') { + srcStr.chop(1); + break; + } else + break; + } + return srcStr; +} +} // namespace + +//============================================================================= +/*! \class StartupPopup + \brief The StartupPopup class provides a modal dialog to + bring up recent files or create a new scene. + + Inherits \b Dialog. +*/ +//----------------------------------------------------------------------------- + +StartupPopup::StartupPopup() + : Dialog(TApp::instance()->getMainWindow(), true, true, "StartupPopup") { + setWindowTitle(tr("OpenToonz Startup")); + + m_projectBox = new QGroupBox(tr("Choose Project"), this); + m_sceneBox = new QGroupBox(tr("Create a New Scene"), this); + m_recentBox = new QGroupBox(tr("Open Scene"), this); + m_projectBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_nameFld = new LineEdit(this); + m_pathFld = new FileField(this); + m_sceneNameLabel = new QLabel(tr("Scene Name:")); + m_widthLabel = new QLabel(tr("Width:"), this); + m_widthFld = new MeasuredDoubleLineEdit(this); + m_heightLabel = new QLabel(tr("Height:"), this); + m_heightFld = new MeasuredDoubleLineEdit(this); + m_dpiLabel = new QLabel(tr("DPI:"), this); + m_dpiFld = new DoubleLineEdit(this, 120); + m_resXLabel = new QLabel(tr("X"), this); + m_resXFld = new DoubleLineEdit(this); + m_resYFld = new DoubleLineEdit(this); + m_resTextLabel = new QLabel(tr("Resolution:"), this); + m_fpsLabel = new QLabel(tr("Frame Rate:"), this); + m_fpsFld = new DoubleLineEdit(this, 24.0); + m_cameraSettingsWidget = new CameraSettingsWidget(false); + m_presetCombo = new QComboBox(this); + m_unitsCB = new QComboBox(this); + m_addPresetBtn = new QPushButton(tr("Add"), this); + m_removePresetBtn = new QPushButton(tr("Remove"), this); + m_showAtStartCB = new QCheckBox(tr("Show this at startup"), this); + QPushButton *createButton = new QPushButton(tr("Create Scene"), this); + QPushButton *newProjectButton = new QPushButton(tr("New Project..."), this); + QPushButton *loadOtherSceneButton = + new QPushButton(tr("Open Another Scene..."), this); + m_projectsCB = new QComboBox(this); + QStringList type; + type << tr("pixel") << tr("cm") << tr("mm") << tr("inch") << tr("field"); + m_unitsCB->addItems(type); + + // Exclude all character which cannot fit in a filepath (Win). + // Dots are also prohibited since they are internally managed by Toonz. + QRegExp rx("[^\\\\/:?*.\"<>|]+"); + m_nameFld->setValidator(new QRegExpValidator(rx, this)); + + m_widthFld->setMeasure("camera.lx"); + m_heightFld->setMeasure("camera.ly"); + + m_widthFld->setRange(0.1, (std::numeric_limits::max)()); + m_heightFld->setRange(0.1, (std::numeric_limits::max)()); + m_fpsFld->setRange(1.0, (std::numeric_limits::max)()); + m_dpiFld->setRange(1.0, (std::numeric_limits::max)()); + m_resXFld->setRange(0.1, (std::numeric_limits::max)()); + m_resYFld->setRange(0.1, (std::numeric_limits::max)()); + m_showAtStartCB->setChecked(Preferences::instance()->isStartupPopupEnabled()); + m_showAtStartCB->setStyleSheet("QCheckBox{ background-color: none; }"); + m_addPresetBtn->setStyleSheet( + "QPushButton { padding-left: 4px; padding-right: 4px;}"); + m_removePresetBtn->setStyleSheet( + "QPushButton { padding-left: 4px; padding-right: 4px;}"); + QLabel *label = new QLabel(); + label->setPixmap(QPixmap(":Resources/startup.png")); + m_projectBox->setObjectName("SolidLineFrame"); + m_sceneBox->setObjectName("SolidLineFrame"); + m_recentBox->setObjectName("SolidLineFrame"); + m_projectBox->setContentsMargins(10, 10, 10, 10); + m_sceneBox->setContentsMargins(10, 10, 10, 10); + m_recentBox->setContentsMargins(10, 10, 10, 10); + m_recentBox->setFixedWidth(200); + m_sceneBox->setMinimumWidth(480); + m_projectBox->setMinimumWidth(480); + m_buttonFrame->setFixedHeight(30); + //--- layout + m_topLayout->setMargin(0); + m_topLayout->setSpacing(0); + { + QGridLayout *guiLay = new QGridLayout(); + QHBoxLayout *projectLay = new QHBoxLayout(); + QGridLayout *newSceneLay = new QGridLayout(); + m_recentSceneLay = new QVBoxLayout(); + guiLay->setMargin(10); + guiLay->setVerticalSpacing(10); + guiLay->setHorizontalSpacing(10); + + guiLay->addWidget(label, 0, 0, 1, 2, Qt::AlignLeft); + + projectLay->setSpacing(8); + projectLay->setMargin(8); + { + projectLay->addWidget(m_projectsCB, 1); + projectLay->addWidget(newProjectButton, 0); + } + m_projectBox->setLayout(projectLay); + guiLay->addWidget(m_projectBox, 1, 0, 1, 1, Qt::AlignCenter); + + newSceneLay->setMargin(8); + newSceneLay->setVerticalSpacing(8); + newSceneLay->setHorizontalSpacing(8); + { + // Scene Name + newSceneLay->addWidget(m_sceneNameLabel, 0, 0, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_nameFld, 0, 1, 1, 3); + + // Save In + newSceneLay->addWidget(new QLabel(tr("Save In:")), 1, 0, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_pathFld, 1, 1, 1, 3); + newSceneLay->addWidget(new QLabel(tr("Camera Size:")), 2, 0, + Qt::AlignRight | Qt::AlignVCenter); + QHBoxLayout *resListLay = new QHBoxLayout(); + resListLay->setSpacing(3); + resListLay->setMargin(1); + { + resListLay->addWidget(m_presetCombo, 1); + resListLay->addWidget(m_addPresetBtn, 0); + resListLay->addWidget(m_removePresetBtn, 0); + } + newSceneLay->addLayout(resListLay, 2, 1, 1, 3, Qt::AlignLeft); + + // Width - Height + newSceneLay->addWidget(m_widthLabel, 3, 0, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_widthFld, 3, 1); + newSceneLay->addWidget(m_heightLabel, 3, 2, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_heightFld, 3, 3); + + newSceneLay->addWidget(m_resTextLabel, 4, 0, 1, 1, Qt::AlignRight); + newSceneLay->addWidget(m_resXFld, 4, 1); + newSceneLay->addWidget(m_resXLabel, 4, 2, 1, 1, Qt::AlignCenter); + newSceneLay->addWidget(m_resYFld, 4, 3); + newSceneLay->addWidget(new QLabel(tr("Units:")), 5, 0, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_unitsCB, 5, 1, 1, 1); + newSceneLay->addWidget(m_dpiLabel, 5, 2, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_dpiFld, 5, 3, 1, 1); + newSceneLay->addWidget(m_fpsLabel, 6, 0, + Qt::AlignRight | Qt::AlignVCenter); + newSceneLay->addWidget(m_fpsFld, 6, 1, 1, 1); + newSceneLay->addWidget(createButton, 7, 1, 1, 3, Qt::AlignLeft); + } + m_sceneBox->setLayout(newSceneLay); + guiLay->addWidget(m_sceneBox, 2, 0, 4, 1, Qt::AlignLeft); + + m_recentSceneLay->setMargin(5); + m_recentSceneLay->setSpacing(2); + { + // Recent Scene List + m_recentBox->setLayout(m_recentSceneLay); + guiLay->addWidget(m_recentBox, 1, 1, 4, 1, Qt::AlignTop); + guiLay->addWidget(loadOtherSceneButton, 5, 1, 1, 1, Qt::AlignRight); + } + m_topLayout->addLayout(guiLay, 0); + } + + m_buttonLayout->setMargin(0); + m_buttonLayout->setSpacing(10); + { m_buttonLayout->addWidget(m_showAtStartCB, Qt::AlignLeft); } + + TApp *app = TApp::instance(); + TSceneHandle *sceneHandle = app->getCurrentScene(); + + //---- signal-slot connections + bool ret = true; + ret = ret && connect(sceneHandle, SIGNAL(sceneChanged()), this, + SLOT(onSceneChanged())); + ret = ret && connect(sceneHandle, SIGNAL(sceneSwitched()), this, + SLOT(onSceneChanged())); + ret = ret && connect(newProjectButton, SIGNAL(clicked()), this, + SLOT(onNewProjectButtonPressed())); + ret = ret && connect(loadOtherSceneButton, SIGNAL(clicked()), this, + SLOT(onLoadSceneButtonPressed())); + ret = ret && connect(m_projectsCB, SIGNAL(currentIndexChanged(int)), + SLOT(onProjectChanged(int))); + ret = ret && + connect(createButton, SIGNAL(clicked()), this, SLOT(onCreateButton())); + ret = ret && connect(m_showAtStartCB, SIGNAL(stateChanged(int)), this, + SLOT(onShowAtStartChanged(int))); + ret = ret && connect(m_widthFld, SIGNAL(valueChanged()), this, + SLOT(updateResolution())); + ret = ret && connect(m_heightFld, SIGNAL(valueChanged()), this, + SLOT(updateResolution())); + ret = ret && + connect(m_resXFld, SIGNAL(valueChanged()), this, SLOT(updateSize())); + ret = ret && + connect(m_resYFld, SIGNAL(valueChanged()), this, SLOT(updateSize())); + ret = ret && connect(m_dpiFld, SIGNAL(editingFinished()), this, + SLOT(onDpiChanged())); + ret = ret && connect(m_presetCombo, SIGNAL(activated(const QString &)), + SLOT(onPresetSelected(const QString &))); + ret = ret && connect(m_addPresetBtn, SIGNAL(clicked()), SLOT(addPreset())); + ret = ret && connect(m_unitsCB, SIGNAL(currentIndexChanged(int)), + SLOT(onCameraUnitChanged(int))); + ret = ret && + connect(m_removePresetBtn, SIGNAL(clicked()), SLOT(removePreset())); + ret = ret && connect(m_nameFld, SIGNAL(returnPressedNow()), createButton, + SLOT(animateClick())); + assert(ret); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::showEvent(QShowEvent *) { + loadPresetList(); + updateProjectCB(); + m_nameFld->setFocus(); + m_pathFld->setPath(TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProject() + ->getScenesPath() + .getQString()); + TDimensionD cameraSize = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getCurrentCamera() + ->getSize(); + TDimension cameraRes = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getCurrentCamera() + ->getRes(); + double fps = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProperties() + ->getOutputProperties() + ->getFrameRate(); + m_widthFld->setValue(cameraSize.lx); + m_heightFld->setValue(cameraSize.ly); + if (Preferences::instance()->getCameraUnits() == "pixel") { + m_widthFld->setDecimals(0); + m_heightFld->setDecimals(0); + m_resTextLabel->hide(); + m_resXFld->hide(); + m_resYFld->hide(); + m_resXLabel->hide(); + m_dpiFld->hide(); + m_dpiLabel->hide(); + } else { + m_widthFld->setDecimals(4); + m_heightFld->setDecimals(4); + m_resXFld->show(); + m_resYFld->show(); + m_resXLabel->show(); + m_resTextLabel->show(); + m_dpiFld->show(); + m_dpiLabel->show(); + } + + m_fpsFld->setValue(fps); + m_unitsCB->setCurrentText(Preferences::instance()->getCameraUnits()); + m_dpi = cameraRes.lx / cameraSize.lx; + m_xRes = cameraRes.lx; + m_yRes = cameraRes.ly; + m_resXFld->setValue(m_xRes); + m_resYFld->setValue(m_yRes); + m_resXFld->setDecimals(0); + m_resYFld->setDecimals(0); + m_dpiFld->setValue(m_dpi); + + int boxWidth = m_sceneBox->width(); + int boxHeight = m_sceneBox->height(); + m_sceneBox->setFixedWidth(boxWidth); + m_projectBox->setFixedWidth(boxWidth); + m_recentBox->setMinimumHeight(boxHeight); + + // update recent scenes + // clear items if they exist first + + if (m_recentSceneLay->count() > 0) { + QLayoutItem *child; + while (m_recentSceneLay->count() != 0) { + child = m_recentSceneLay->takeAt(0); + delete child; + } + } + + m_sceneNames = RecentFiles::instance()->getFilesNameList(RecentFiles::Scene); + m_recentNamesLabels = QVector(m_sceneNames.count()); + + if (m_sceneNames.count() <= 0) { + m_recentSceneLay->addWidget(new QLabel(tr("No Recent Scenes"), this), 1, + Qt::AlignTop); + } else { + int i = 0; + for (QString name : m_sceneNames) { + if (i > 9) break; // box can hold 10 scenes + QString justName = QString::fromStdString(TFilePath(name).getName()); + m_recentNamesLabels[i] = new StartupLabel(justName, this, i); + m_recentNamesLabels[i]->setToolTip( + name.remove(0, name.indexOf(" ") + 1)); // remove "#. " prefix + m_recentSceneLay->addWidget(m_recentNamesLabels[i], i, Qt::AlignTop); + i++; + } + m_recentSceneLay->addStretch(100); + } + + bool ret = true; + for (int i = 0; i < m_recentNamesLabels.count() && i < 7; i++) { + ret = ret && connect(m_recentNamesLabels[i], SIGNAL(wasClicked(int)), this, + SLOT(onRecentSceneClicked(int))); + } + assert(ret); + // center window + this->move(QApplication::desktop()->screen()->rect().center() - + this->rect().center()); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onCreateButton() { + if (m_nameFld->text().trimmed() == "") { + DVGui::warning(tr("The name cannot be empty.")); + m_nameFld->setFocus(); + return; + } + if (!TSystem::doesExistFileOrLevel(TFilePath(m_pathFld->getPath()))) { + DVGui::warning(tr("The chosen file path is not valid.")); + m_pathFld->setFocus(); + return; + } + + if (m_widthFld->getValue() < 1) { + DVGui::warning(tr("The width must be 1 or more.")); + m_widthFld->setFocus(); + return; + } + if (m_heightFld->getValue() < 1) { + DVGui::warning(tr("The height must be 1 or more.")); + m_heightFld->setFocus(); + return; + } + if (m_fpsFld->getValue() < 1) { + DVGui::warning(tr("The frame rate must be 1 or more.")); + m_fpsFld->setFocus(); + return; + } + if (TSystem::doesExistFileOrLevel( + TFilePath(m_pathFld->getPath()) + + TFilePath(m_nameFld->text().trimmed().toStdWString() + L".tnz"))) { + QString question; + question = QObject::tr( + "The file name already exists." + "\nDo you want to overwrite it?"); + int ret = DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No"), 0); + if (ret == 0 || ret == 2) { + // no (or closed message box window) + return; + ; + } + } + CommandManager::instance()->execute(MI_NewScene); + TApp::instance()->getCurrentScene()->getScene()->setScenePath( + TFilePath(m_pathFld->getPath()) + + TFilePath(m_nameFld->text().trimmed().toStdWString())); + TDimensionD size = + TDimensionD(m_widthFld->getValue(), m_heightFld->getValue()); + TDimension res = TDimension(m_xRes, m_yRes); + double fps = m_fpsFld->getValue(); + TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProperties() + ->getOutputProperties() + ->setFrameRate(fps); + TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera()->setSize( + size); + TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera()->setRes( + res); + // this one is debatable - should the scene be saved right away? + // IoCmd::saveScene(); + // this makes sure the scene viewers update to the right fps + TApp::instance()->getCurrentScene()->notifySceneSwitched(); + + hide(); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::updateProjectCB() { + m_updating = true; + m_projectPaths.clear(); + m_projectsCB->clear(); + + TFilePath sandboxFp = TProjectManager::instance()->getSandboxProjectFolder() + + "sandbox_otprj.xml"; + m_projectPaths.push_back(sandboxFp); + m_projectsCB->addItem("sandbox"); + + std::vector prjRoots; + TProjectManager::instance()->getProjectRoots(prjRoots); + for (int i = 0; i < prjRoots.size(); i++) { + TFilePathSet fps; + TSystem::readDirectory_Dir_ReadExe(fps, prjRoots[i]); + + TFilePathSet::iterator it; + for (it = fps.begin(); it != fps.end(); ++it) { + TFilePath fp(*it); + if (TProjectManager::instance()->isProject(fp)) { + m_projectPaths.push_back( + TProjectManager::instance()->projectFolderToProjectPath(fp)); + m_projectsCB->addItem(QString::fromStdString(fp.getName())); + } + } + } + int i; + for (i = 0; i < m_projectPaths.size(); i++) { + if (TProjectManager::instance()->getCurrentProjectPath() == + m_projectPaths[i]) { + m_projectsCB->setCurrentIndex(i); + break; + } + } + m_pathFld->setPath(TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProject() + ->getScenesPath() + .getQString()); + m_updating = false; +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onProjectChanged(int index) { + if (m_updating) return; + TFilePath projectFp = m_projectPaths[index]; + + TProjectManager::instance()->setCurrentProjectPath(projectFp); + + IoCmd::newScene(); + m_pathFld->setPath(TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProject() + ->getScenesPath() + .getQString()); + m_fpsFld->setValue(TApp::instance() + ->getCurrentScene() + ->getScene() + ->getProperties() + ->getOutputProperties() + ->getFrameRate()); + TDimension res = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getCurrentCamera() + ->getRes(); + m_xRes = res.lx; + m_yRes = res.ly; + m_resXFld->setValue(m_xRes); + m_resYFld->setValue(m_yRes); + TDimensionD size = TApp::instance() + ->getCurrentScene() + ->getScene() + ->getCurrentCamera() + ->getSize(); + m_widthFld->setValue(size.lx); + m_heightFld->setValue(size.ly); + m_dpi = m_xRes / size.lx; + m_dpiFld->setValue(m_dpi); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::loadPresetList() { + m_presetCombo->clear(); + m_presetCombo->addItem("..."); + m_presetListFile = ToonzFolder::getReslistPath(false).getQString(); + QFile file(m_presetListFile); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&file); + while (!in.atEnd()) { + QString line = in.readLine().trimmed(); + if (line != "") m_presetCombo->addItem(line); + } + } + m_presetCombo->setCurrentIndex(0); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::savePresetList() { + QFile file(m_presetListFile); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; + QTextStream out(&file); + int n = m_presetCombo->count(); + for (int i = 1; i < n; i++) out << m_presetCombo->itemText(i) << "\n"; +} + +//----------------------------------------------------------------------------- + +void StartupPopup::addPreset() { + int xRes = (int)(m_widthFld->getValue() * m_dpi); + int yRes = (int)(m_heightFld->getValue() * m_dpi); + double lx = m_widthFld->getValue(); + double ly = m_heightFld->getValue(); + double ar = m_widthFld->getValue() / m_heightFld->getValue(); + + QString presetString; + presetString = QString::number(xRes) + "x" + QString::number(yRes) + ", " + + removeZeros(QString::number(lx)) + "x" + + removeZeros(QString::number(ly)) + ", " + + aspectRatioValueToString(ar); + + bool ok; + QString qs; + while (1) { + qs = DVGui::getText(tr("Preset name"), + tr("Enter the name for %1").arg(presetString), "", &ok); + + if (!ok) return; + + if (qs.indexOf(",") != -1) + QMessageBox::warning(this, tr("Error : Preset Name is Invalid"), + tr("The preset name must not use ','(comma).")); + else + break; + } + + int oldn = m_presetCombo->count(); + m_presetCombo->addItem(qs + "," + presetString); + int newn = m_presetCombo->count(); + m_presetCombo->blockSignals(true); + m_presetCombo->setCurrentIndex(m_presetCombo->count() - 1); + m_presetCombo->blockSignals(false); + + savePresetList(); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::removePreset() { + int index = m_presetCombo->currentIndex(); + if (index <= 0) return; + + // confirmation dialog + int ret = DVGui::MsgBox(QObject::tr("Deleting \"%1\".\nAre you sure?") + .arg(m_presetCombo->currentText()), + QObject::tr("Delete"), QObject::tr("Cancel")); + if (ret == 0 || ret == 2) return; + + m_presetCombo->removeItem(index); + m_presetCombo->setCurrentIndex(0); + savePresetList(); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onPresetSelected(const QString &str) { + if (str == custom || str.isEmpty()) return; + QString name, arStr; + int xres = 0, yres = 0; + double fx = -1.0, fy = -1.0; + QString xoffset = "", yoffset = ""; + double ar; + + if (parsePresetString(str, name, xres, yres, fx, fy, xoffset, yoffset, ar, + false)) { + m_xRes = xres; + m_yRes = yres; + // The current solution is to preserve the DPI so that scenes are less + // likely to become incompatible with pixels only mode in the future + // Commented below is the default behavior of the camera settings widget + // m_widthFld->setValue(m_heightFld->getValue() * ar); + // m_dpiFld->setValue(m_xRes / m_widthFld->getValue()); + + // here is the system that preserves dpi + m_widthFld->setValue((double)xres / (double)m_dpi); + m_heightFld->setValue((double)yres / (double)m_dpi); + if (Preferences::instance()->getPixelsOnly()) { + m_widthFld->setValue((double)xres / Stage::standardDpi); + m_heightFld->setValue((double)yres / Stage::standardDpi); + m_dpiFld->setValue(Stage::standardDpi); + } + m_resXFld->setValue(m_xRes); + m_resYFld->setValue(m_yRes); + } else { + QMessageBox::warning( + this, tr("Bad camera preset"), + tr("'%1' doesn't seem to be a well formed camera preset. \n" + "Possibly the preset file has been corrupted") + .arg(str)); + } +} + +//-------------------------------------------------------------------------- + +bool StartupPopup::parsePresetString(const QString &str, QString &name, + int &xres, int &yres, double &fx, + double &fy, QString &xoffset, + QString &yoffset, double &ar, + bool forCleanup) { + /* + parsing preset string with QString::split(). + !NOTE! fx/fy (camera size in inch) and xoffset/yoffset (camera offset used in + cleanup camera) are optional, + in order to keep compatibility with default (Harlequin's) reslist.txt + */ + + QStringList tokens = str.split(",", QString::SkipEmptyParts); + + if (!(tokens.count() == 3 || + (!forCleanup && tokens.count() == 4) || /*- with "fx x fy" token -*/ + (forCleanup && + tokens.count() == + 6))) /*- with "fx x fy", xoffset and yoffset tokens -*/ + return false; + /*- name -*/ + name = tokens[0]; + + /*- xres, yres (like: 1024x768) -*/ + QStringList values = tokens[1].split("x"); + if (values.count() != 2) return false; + bool ok; + xres = values[0].toInt(&ok); + if (!ok) return false; + yres = values[1].toInt(&ok); + if (!ok) return false; + + if (tokens.count() >= 4) { + /*- fx, fy -*/ + values = tokens[2].split("x"); + if (values.count() != 2) return false; + fx = values[0].toDouble(&ok); + if (!ok) return false; + fy = values[1].toDouble(&ok); + if (!ok) return false; + + /*- xoffset, yoffset -*/ + if (forCleanup) { + xoffset = tokens[3]; + yoffset = tokens[4]; + /*- remove single space -*/ + if (xoffset.startsWith(' ')) xoffset.remove(0, 1); + if (yoffset.startsWith(' ')) yoffset.remove(0, 1); + } + } + + /*- AR -*/ + ar = aspectRatioStringToValue(tokens.last()); + + return true; +} + +//----------------------------------------------------------------------------- + +double StartupPopup::aspectRatioStringToValue(const QString &s) { + if (s == "") { + return 1; + } + int i = s.indexOf("/"); + if (i <= 0 || i + 1 >= s.length()) return s.toDouble(); + int num = s.left(i).toInt(); + int den = s.mid(i + 1).toInt(); + if (den <= 0) den = 1; + return (double)num / (double)den; +} + +//----------------------------------------------------------------------------- + +// A/R : value => string (e.g. '4/3' or '1.23') +QString StartupPopup::aspectRatioValueToString(double value, int width, + int height) { + double v = value; + + if (width != 0 && height != 0) { + if (areAlmostEqual(value, (double)width / (double)height, 1e-3)) + return QString("%1/%2").arg(width).arg(height); + } + + double iv = tround(v); + if (fabs(iv - v) > 0.01) { + for (int d = 2; d < 20; d++) { + int n = tround(v * d); + if (fabs(n - v * d) <= 0.01) + return QString::number(n) + "/" + QString::number(d); + } + return QString::number(value, 'f', 5); + } else { + return QString::number((int)iv); + } +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onNewProjectButtonPressed() { + CommandManager::instance()->execute(MI_NewProject); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onSceneChanged() { + // close the box if a recent scene has been selected + if (!TApp::instance()->getCurrentScene()->getScene()->isUntitled()) { + hide(); + } else { + updateProjectCB(); + } +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onDpiChanged() { + if (Preferences::instance()->getPixelsOnly()) { + m_dpi = Stage::standardDpi; + m_dpiFld->setValue(Stage::standardDpi); + updateResolution(); + } else { + m_dpi = m_dpiFld->getValue(); + updateResolution(); + } +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onLoadSceneButtonPressed() { + CommandManager::instance()->execute(MI_LoadScene); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onRecentSceneClicked(int index) { + if (index < 0) return; + QString path = + RecentFiles::instance()->getFilePath(index, RecentFiles::Scene); + IoCmd::loadScene(TFilePath(path.toStdWString()), false); + RecentFiles::instance()->moveFilePath(index, 0, RecentFiles::Scene); + RecentFiles::instance()->refreshRecentFilesMenu(RecentFiles::Scene); + hide(); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onCameraUnitChanged(int index) { + Preferences *pref = Preferences::instance(); + QStringList type; + type << tr("pixel") << tr("cm") << tr("mm") << tr("inch") << tr("field"); + + double width = m_widthFld->getValue(); + double height = m_heightFld->getValue(); + if (index != 0) { + pref->setPixelsOnly(false); + pref->setCameraUnits(type[index].toStdString()); + m_widthFld->setDecimals(4); + m_heightFld->setDecimals(4); + m_resTextLabel->show(); + m_resXFld->show(); + m_resYFld->show(); + m_resXLabel->show(); + m_dpiFld->show(); + m_dpiLabel->show(); + m_widthFld->setMeasure("camera.lx"); + m_heightFld->setMeasure("camera.ly"); + m_widthFld->setValue(width); + m_heightFld->setValue(height); + } else { + pref->setPixelsOnly(true); + pref->setUnits("pixel"); + pref->setCameraUnits("pixel"); + m_widthFld->setDecimals(0); + m_heightFld->setDecimals(0); + m_resTextLabel->hide(); + m_resXFld->hide(); + m_resYFld->hide(); + m_resXLabel->hide(); + m_dpiFld->hide(); + m_dpiLabel->hide(); + m_dpiFld->setValue(Stage::standardDpi); + m_widthFld->setMeasure("camera.lx"); + m_heightFld->setMeasure("camera.ly"); + m_widthFld->setValue(m_xRes / Stage::standardDpi); + m_heightFld->setValue(m_yRes / Stage::standardDpi); + } +} + +//----------------------------------------------------------------------------- + +void StartupPopup::onShowAtStartChanged(int index) { + Preferences::instance()->enableStartupPopup(index); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::updateResolution() { + if (Preferences::instance()->getPixelsOnly()) { + if (m_dpiFld->getValue() != Stage::standardDpi) { + m_dpiFld->setValue(Stage::standardDpi); + } + m_xRes = m_widthFld->getValue() * Stage::standardDpi; + m_yRes = m_heightFld->getValue() * Stage::standardDpi; + m_resXFld->setValue(m_xRes); + m_resYFld->setValue(m_yRes); + } else { + m_xRes = m_widthFld->getValue() * m_dpi; + m_yRes = m_heightFld->getValue() * m_dpi; + m_resXFld->setValue(m_xRes); + m_resYFld->setValue(m_yRes); + } + m_presetCombo->setCurrentIndex(0); +} + +//----------------------------------------------------------------------------- + +void StartupPopup::updateSize() { + m_xRes = m_resXFld->getValue(); + m_yRes = m_resYFld->getValue(); + if (Preferences::instance()->getPixelsOnly()) { + if (m_dpiFld->getValue() != Stage::standardDpi) { + m_dpiFld->setValue(Stage::standardDpi); + } + m_widthFld->setValue((double)m_xRes / Stage::standardDpi); + m_heightFld->setValue((double)m_yRes / Stage::standardDpi); + } else { + m_widthFld->setValue((double)m_xRes / m_dpi); + m_heightFld->setValue((double)m_yRes / m_dpi); + } + m_presetCombo->setCurrentIndex(0); +} + +//----------------------------------------------------------------------------- + +StartupLabel::StartupLabel(const QString &text, QWidget *parent, int index) + : QLabel(parent), m_index(index) { + setText(text); + setObjectName("StartupLabel"); +} + +StartupLabel::~StartupLabel() {} + +void StartupLabel::mousePressEvent(QMouseEvent *event) { + m_text = text(); + std::string strText = m_text.toStdString(); + emit wasClicked(m_index); +} + +OpenPopupCommandHandler openStartupPopup(MI_StartupPopup); diff --git a/toonz/sources/toonz/startuppopup.h b/toonz/sources/toonz/startuppopup.h new file mode 100644 index 0000000..cd1e33d --- /dev/null +++ b/toonz/sources/toonz/startuppopup.h @@ -0,0 +1,109 @@ +#pragma once + +#ifndef STARTUPPOPUP_H +#define STARTUPPOPUP_H + +#include "toonzqt/dvdialog.h" +#include "toonzqt/doublefield.h" +#include "toonzqt/intfield.h" +#include "toonzqt/filefield.h" +#include "toonzqt/camerasettingswidget.h" +#include +#include +#include +#include + +// forward declaration +class QLabel; +class QComboBox; +class StartupLabel; + +//============================================================================= +// LevelCreatePopup +//----------------------------------------------------------------------------- + +class StartupPopup final : public DVGui::Dialog { + Q_OBJECT + + DVGui::LineEdit *m_nameFld; + DVGui::FileField *m_pathFld; + QLabel *m_widthLabel; + QLabel *m_heightLabel; + QLabel *m_fpsLabel; + QLabel *m_resXLabel; + QLabel *m_resTextLabel; + QLabel *m_dpiLabel; + QLabel *m_sceneNameLabel; + DVGui::DoubleLineEdit *m_dpiFld; + DVGui::MeasuredDoubleLineEdit *m_widthFld; + DVGui::MeasuredDoubleLineEdit *m_heightFld; + DVGui::DoubleLineEdit *m_fpsFld; + DVGui::DoubleLineEdit *m_resXFld; + DVGui::DoubleLineEdit *m_resYFld; + QList m_sceneNames; + QList m_projectPaths; + QCheckBox *m_showAtStartCB; + QComboBox *m_projectsCB; + QComboBox *m_unitsCB; + QPushButton *m_loadOtherSceneButton; + QPushButton *m_newProjectButton; + QComboBox *m_presetCombo; + QPushButton *m_addPresetBtn, *m_removePresetBtn; + CameraSettingsWidget *m_cameraSettingsWidget; + double m_dpi; + int m_xRes, m_yRes; + bool m_updating = false; + QString m_presetListFile; + QGroupBox *m_projectBox; + QGroupBox *m_sceneBox; + QGroupBox *m_recentBox; + QVBoxLayout *m_recentSceneLay; + QVector m_recentNamesLabels; + +public: + StartupPopup(); + +protected: + void showEvent(QShowEvent *) override; + void loadPresetList(); + void savePresetList(); + QString aspectRatioValueToString(double value, int width = 0, int height = 0); + double aspectRatioStringToValue(const QString &s); + bool parsePresetString(const QString &str, QString &name, int &xres, + int &yres, double &fx, double &fy, QString &xoffset, + QString &yoffset, double &ar, bool forCleanup = false); + +public slots: + void onRecentSceneClicked(int index); + void onCreateButton(); + void onShowAtStartChanged(int index); + void updateProjectCB(); + void onProjectChanged(int index); + void onNewProjectButtonPressed(); + void onLoadSceneButtonPressed(); + void onSceneChanged(); + void updateResolution(); + void updateSize(); + void onDpiChanged(); + void addPreset(); + void removePreset(); + void onPresetSelected(const QString &str); + void onCameraUnitChanged(int index); +}; + +class StartupLabel : public QLabel { + Q_OBJECT +public: + explicit StartupLabel(const QString &text = "", QWidget *parent = 0, + int index = -1); + ~StartupLabel(); + QString m_text; + int m_index; +signals: + void wasClicked(int index); + +protected: + void mousePressEvent(QMouseEvent *event); +}; + +#endif // STARTUPPOPUP_H diff --git a/toonz/sources/toonz/tapp.cpp b/toonz/sources/toonz/tapp.cpp index a6ef8b2..698fe26 100644 --- a/toonz/sources/toonz/tapp.cpp +++ b/toonz/sources/toonz/tapp.cpp @@ -673,16 +673,25 @@ void TApp::autosave() { } else m_autosaveSuspended = false; - if (scene->isUntitled()) { + if (scene->isUntitled() && + Preferences::instance()->isAutosaveSceneEnabled()) { DVGui::warning( - tr("It is not possible to save automatically an untitled scene.")); + tr("It is not possible to automatically save an untitled scene.")); return; } DVGui::ProgressDialog pb( "Autosaving scene..." + toQString(scene->getScenePath()), 0, 0, 1); pb.show(); - IoCmd::saveScene(); + Preferences *pref = Preferences::instance(); + if (pref->isAutosaveSceneEnabled() && pref->isAutosaveOtherFilesEnabled()) { + IoCmd::saveAll(); + } else if (pref->isAutosaveSceneEnabled()) { + IoCmd::saveScene(); + } else if (pref->isAutosaveOtherFilesEnabled()) { + IoCmd::saveNonSceneFiles(); + } + pb.setValue(1); } @@ -705,7 +714,7 @@ void TApp::onStartAutoSave() { //----------------------------------------------------------------------------- void TApp::onStopAutoSave() { - assert(!Preferences::instance()->isAutosaveEnabled()); + // assert(!Preferences::instance()->isAutosaveEnabled()); m_autosaveTimer->stop(); } diff --git a/toonz/sources/toonz/toonz.qrc b/toonz/sources/toonz/toonz.qrc index 75aa7a1..3ad3f78 100644 --- a/toonz/sources/toonz/toonz.qrc +++ b/toonz/sources/toonz/toonz.qrc @@ -264,6 +264,7 @@ Resources/standard.png Resources/standard_on.png Resources/standard_over.png + Resources/startup.png Resources/start_off.png Resources/start_on.png Resources/stop_off.png @@ -442,5 +443,8 @@ Resources/finger_rollover.svg Resources/ruler.svg Resources/ruler_rollover.svg + Resources/locator.png + Resources/locator_click.png + Resources/locator_over.png diff --git a/toonz/sources/toonzlib/convert2tlv.cpp b/toonz/sources/toonzlib/convert2tlv.cpp index 8e9c529..2fbed64 100644 --- a/toonz/sources/toonzlib/convert2tlv.cpp +++ b/toonz/sources/toonzlib/convert2tlv.cpp @@ -566,6 +566,18 @@ TPalette *Convert2Tlv::buildPalette() { page->addStyle(stylesToBeAddedToPage.at(s)); } + /* + If the palette path is empty, an initial palette with four colors are set in + the palette here. + ( see Convert2Tlv::init() ) So here I make the latter three styles in the + initial palette to set + "AutoPaint" options. + */ + if (m_palettePath.isEmpty()) { + assert(m_palette->getStyleCount() >= 5); + for (int id = 2; id <= 4; id++) m_palette->getStyle(id)->setFlags(1); + } + if (!m_appendDefaultPalette) return m_palette; /*-- Adding styles in the default palette to the result palette, starts here @@ -810,11 +822,17 @@ bool Convert2Tlv::init(std::string &errorMessage) { m_it = m_level1->begin(); - /*- 既定のパレットを作る。黒、赤、青、緑の順 -*/ - m_colorMap[TPixel::Black] = ++m_lastIndex; - m_colorMap[TPixel::Red] = ++m_lastIndex; - m_colorMap[TPixel::Blue] = ++m_lastIndex; - m_colorMap[TPixel::Green] = ++m_lastIndex; + /*- + If the palette is empty, make an initial palette with black, red, blue and + green styles. + For the latter three styles the "autopaint" option should be set. + -*/ + if (m_lastIndex == 0) { + m_colorMap[TPixel::Black] = ++m_lastIndex; + m_colorMap[TPixel::Red] = ++m_lastIndex; + m_colorMap[TPixel::Blue] = ++m_lastIndex; + m_colorMap[TPixel::Green] = ++m_lastIndex; + } return true; } diff --git a/toonz/sources/toonzlib/palettecmd.cpp b/toonz/sources/toonzlib/palettecmd.cpp index 5e16930..c23f12e 100644 --- a/toonz/sources/toonzlib/palettecmd.cpp +++ b/toonz/sources/toonzlib/palettecmd.cpp @@ -33,6 +33,7 @@ #include "tstroke.h" #include "tregion.h" #include "tlevel_io.h" +#include "tpixelutils.h" #include "historytypes.h" @@ -45,6 +46,8 @@ #include #include +#include + //=================================================================== void findPaletteLevels(set &levels, int &rowIndex, @@ -1168,3 +1171,177 @@ void PaletteCmd::renamePaletteStyle(TPaletteHandle *paletteHandle, paletteHandle->notifyColorStyleChanged(false); TUndoManager::manager()->add(undo); } + +//============================================================================= +// organizePaletteStyle +// called in ColorModelViewer::pick() - move selected style to the first page +//----------------------------------------------------------------------------- +namespace { + +class setStylePickedPositionUndo final : public TUndo { + TPaletteHandle *m_paletteHandle; // Used in undo and redo to notify change + int m_styleId; + TPaletteP m_palette; + TPoint m_newPos; + TPoint m_oldPos; + +public: + setStylePickedPositionUndo(TPaletteHandle *paletteHandle, int styleId, + const TPoint &newPos) + : m_paletteHandle(paletteHandle), m_styleId(styleId), m_newPos(newPos) { + m_palette = paletteHandle->getPalette(); + assert(m_palette); + TColorStyle *style = m_palette->getStyle(m_styleId); + assert(style); + m_oldPos = style->getPickedPosition(); + } + void undo() const override { + TColorStyle *style = m_palette->getStyle(m_styleId); + assert(style); + style->setPickedPosition(m_oldPos); + m_paletteHandle->notifyColorStyleChanged(false); + } + void redo() const override { + TColorStyle *style = m_palette->getStyle(m_styleId); + assert(style); + style->setPickedPosition(m_newPos); + m_paletteHandle->notifyColorStyleChanged(false); + } + int getSize() const override { return sizeof *this; } + QString getHistoryString() override { + return QObject::tr("Set Picked Position of Style#%1 in Palette%2 : %3,%4") + .arg(QString::number(m_styleId)) + .arg(QString::fromStdWString(m_palette->getPaletteName())) + .arg(QString::number(m_newPos.x)) + .arg(QString::number(m_newPos.y)); + } + int getHistoryType() override { return HistoryType::Palette; } +}; +} + +void PaletteCmd::organizePaletteStyle(TPaletteHandle *paletteHandle, + int styleId, const TPoint &point) { + if (!paletteHandle) return; + TPalette *palette = paletteHandle->getPalette(); + if (!palette) return; + // if the style is already in the first page, then do nothing + TPalette::Page *page = palette->getStylePage(styleId); + if (!page || page->getIndex() == 0) return; + + int indexInPage = page->search(styleId); + + TUndoManager::manager()->beginBlock(); + + // call arrangeStyles() to move style to the first page + arrangeStyles(paletteHandle, 0, palette->getPage(0)->getStyleCount(), + page->getIndex(), {indexInPage}); + // then set the picked position + setStylePickedPositionUndo *undo = + new setStylePickedPositionUndo(paletteHandle, styleId, point); + undo->redo(); + TUndoManager::manager()->add(undo); + + TUndoManager::manager()->endBlock(); +} + +//============================================================================= +// called in ColorModelViewer::repickFromColorModel(). +// Pick color from the img for all styles with "picked position" value. +//----------------------------------------------------------------------------- +namespace { + +class pickColorByUsingPickedPositionUndo final : public TUndo { + TPaletteHandle *m_paletteHandle; // Used in undo and redo to notify change + TPaletteP m_palette; + QHash> m_styleList; + +public: + pickColorByUsingPickedPositionUndo( + TPaletteHandle *paletteHandle, + QHash> styleList) + : m_paletteHandle(paletteHandle), m_styleList(styleList) { + m_palette = paletteHandle->getPalette(); + assert(m_palette); + } + void undo() const override { + QHash>::const_iterator i = + m_styleList.constBegin(); + while (i != m_styleList.constEnd()) { + TColorStyle *style = m_palette->getStyle(i.key()); + assert(style); + style->setMainColor(i.value().first); + ++i; + } + m_paletteHandle->notifyColorStyleChanged(false); + } + void redo() const override { + QHash>::const_iterator i = + m_styleList.constBegin(); + while (i != m_styleList.constEnd()) { + TColorStyle *style = m_palette->getStyle(i.key()); + assert(style); + style->setMainColor(i.value().second); + ++i; + } + m_paletteHandle->notifyColorStyleChanged(false); + } + int getSize() const override { return sizeof *this; } + QString getHistoryString() override { + return QObject::tr("Update Colors by Using Picked Positions in Palette %1") + .arg(QString::fromStdWString(m_palette->getPaletteName())); + } + int getHistoryType() override { return HistoryType::Palette; } +}; + +TPixel32 pickColor(TRasterImageP ri, const TPoint &rasterPoint) { + TRasterP raster; + raster = ri->getRaster(); + + if (!TRect(raster->getSize()).contains(rasterPoint)) + return TPixel32::Transparent; + + TRaster32P raster32 = raster; + if (raster32) return raster32->pixels(rasterPoint.y)[rasterPoint.x]; + + TRasterGR8P rasterGR8 = raster; + if (rasterGR8) + return toPixel32(rasterGR8->pixels(rasterPoint.y)[rasterPoint.x]); + + return TPixel32::Transparent; +} +} + +void PaletteCmd::pickColorByUsingPickedPosition(TPaletteHandle *paletteHandle, + TImageP img) { + TRasterImageP ri = img; + if (!ri) return; + + TPalette *currentPalette = paletteHandle->getPalette(); + if (!currentPalette) return; + + TDimension imgSize = ri->getRaster()->getSize(); + QHash> styleList; + + // For all styles (starting from #1 as #0 is reserved for the transparent) + for (int sId = 1; sId < currentPalette->getStyleCount(); sId++) { + TColorStyle *style = currentPalette->getStyle(sId); + TPoint pp = style->getPickedPosition(); + // If style has a valid picked position + if (pp != TPoint() && pp.x >= 0 && pp.x < imgSize.lx && pp.y >= 0 && + pp.y < imgSize.ly && style->hasMainColor()) { + TPixel32 beforeColor = style->getMainColor(); + TPixel32 afterColor = pickColor(ri, pp); + style->setMainColor(afterColor); + //... store the style in the list for undo + styleList.insert(sId, QPair(beforeColor, afterColor)); + } + } + + // if some style has been changed, then register undo and notify changes + if (!styleList.isEmpty()) { + pickColorByUsingPickedPositionUndo *undo = + new pickColorByUsingPickedPositionUndo(paletteHandle, styleList); + TUndoManager::manager()->add(undo); + paletteHandle->notifyColorStyleChanged(false, true); // set dirty flag here + } +} \ No newline at end of file diff --git a/toonz/sources/toonzlib/preferences.cpp b/toonz/sources/toonzlib/preferences.cpp index 9af590c..588792e 100644 --- a/toonz/sources/toonzlib/preferences.cpp +++ b/toonz/sources/toonzlib/preferences.cpp @@ -256,6 +256,9 @@ Preferences::Preferences() , m_fitToFlipbookEnabled(false) , m_previewAlwaysOpenNewFlipEnabled(false) , m_autosaveEnabled(false) + , m_autosaveSceneEnabled(true) + , m_autosaveOtherFilesEnabled(true) + , m_startupPopupEnabled(true) , m_defaultViewerEnabled(false) , m_saveUnpaintedInCleanup(true) , m_askForOverrideRender(true) @@ -288,8 +291,11 @@ Preferences::Preferences() , m_multiLayerStylePickerEnabled(false) , m_paletteTypeOnLoadRasterImageAsColorModel(0) , m_showKeyframesOnXsheetCellArea(true) + , m_projectRoot(0x08) + , m_customProjectRoot("") , m_precompute(true) , m_ffmpegTimeout(30) + , m_shortcutPreset("defopentoonz") , m_useNumpadForSwitchingStyles(false) { TCamera camera; m_defLevelType = PLI_XSHLEVEL; @@ -324,6 +330,10 @@ Preferences::Preferences() getValue(*m_settings, "sceneNumberingEnabled", m_sceneNumberingEnabled); getValue(*m_settings, "animationSheetEnabled", m_animationSheetEnabled); getValue(*m_settings, "autosaveEnabled", m_autosaveEnabled); + getValue(*m_settings, "autosaveSceneEnabled", m_autosaveSceneEnabled); + getValue(*m_settings, "autosaveOtherFilesEnabled", + m_autosaveOtherFilesEnabled); + getValue(*m_settings, "startupPopupEnabled", m_startupPopupEnabled); getValue(*m_settings, "defaultViewerEnabled", m_defaultViewerEnabled); getValue(*m_settings, "rasterOptimizedMemory", m_rasterOptimizedMemory); getValue(*m_settings, "saveUnpaintedInCleanup", m_saveUnpaintedInCleanup); @@ -394,6 +404,9 @@ Preferences::Preferences() m_oldCameraUnits = units; // end for pixels only + getValue(*m_settings, "projectRoot", m_projectRoot); + m_customProjectRoot = m_settings->value("customProjectRoot").toString(); + units = m_settings->value("linearUnits").toString(); if (units != "") m_units = units; setUnits(m_units.toStdString()); @@ -549,6 +562,9 @@ Preferences::Preferences() if (ffmpegPath != "") m_ffmpegPath = ffmpegPath; setFfmpegPath(m_ffmpegPath.toStdString()); getValue(*m_settings, "ffmpegTimeout", m_ffmpegTimeout); + QString shortcutPreset = m_settings->value("shortcutPreset").toString(); + if (shortcutPreset != "") m_shortcutPreset = shortcutPreset; + setShortcutPreset(m_shortcutPreset.toStdString()); getValue(*m_settings, "useNumpadForSwitchingStyles", m_useNumpadForSwitchingStyles); } @@ -643,6 +659,27 @@ void Preferences::enableAutosave(bool on) { //----------------------------------------------------------------- +void Preferences::enableAutosaveScene(bool on) { + m_autosaveSceneEnabled = on; + m_settings->setValue("autosaveSceneEnabled", on ? "1" : "0"); +} + +//----------------------------------------------------------------- + +void Preferences::enableAutosaveOtherFiles(bool on) { + m_autosaveOtherFilesEnabled = on; + m_settings->setValue("autosaveOtherFilesEnabled", on ? "1" : "0"); +} + +//----------------------------------------------------------------- + +void Preferences::enableStartupPopup(bool on) { + m_startupPopupEnabled = on; + m_settings->setValue("startupPopupEnabled", on ? "1" : "0"); +} + +//----------------------------------------------------------------- + void Preferences::setAskForOverrideRender(bool on) { m_autosaveEnabled = on; m_settings->setValue("askForOverrideRender", on ? "1" : "0"); @@ -975,6 +1012,22 @@ void Preferences::setPixelsOnly(bool state) { //----------------------------------------------------------------- +void Preferences::setProjectRoot(int index) { + // storing the index of the selection instead of the text + // to make translation work + m_projectRoot = index; + m_settings->setValue("projectRoot", m_projectRoot); +} + +//----------------------------------------------------------------- + +void Preferences::setCustomProjectRoot(std::wstring customProjectRoot) { + m_customProjectRoot = QString::fromStdWString(customProjectRoot); + m_settings->setValue("customProjectRoot", m_customProjectRoot); +} + +//----------------------------------------------------------------- + void Preferences::setUnits(std::string units) { m_units = QString::fromStdString(units); m_settings->setValue("linearUnits", m_units); @@ -1206,6 +1259,13 @@ void Preferences::setFfmpegPath(std::string path) { //----------------------------------------------------------------- +void Preferences::setShortcutPreset(std::string preset) { + m_shortcutPreset = QString::fromStdString(preset); + m_settings->setValue("shortcutPreset", m_shortcutPreset); +} + +//----------------------------------------------------------------- + void Preferences::setPrecompute(bool enabled) { m_precompute = enabled; } //----------------------------------------------------------------- diff --git a/toonz/sources/toonzlib/stagevisitor.cpp b/toonz/sources/toonzlib/stagevisitor.cpp index f3746ab..dc256db 100644 --- a/toonz/sources/toonzlib/stagevisitor.cpp +++ b/toonz/sources/toonzlib/stagevisitor.cpp @@ -602,6 +602,9 @@ void RasterPainter::flushRasterImages() { glDisable(GL_DITHER); glDisable(GL_LOGIC_OP); +/* disable, since these features are never enabled, and cause OpenGL to assert + * on systems that don't support them: see #591 */ +#if 0 #ifdef GL_EXT_convolution glDisable(GL_CONVOLUTION_1D_EXT); glDisable(GL_CONVOLUTION_2D_EXT); @@ -612,6 +615,7 @@ void RasterPainter::flushRasterImages() { glDisable(GL_HISTOGRAM_EXT); glDisable(GL_MINMAX_EXT); #endif +#endif #ifdef GL_EXT_texture3D glDisable(GL_TEXTURE_3D_EXT); diff --git a/toonz/sources/toonzlib/studiopalettecmd.cpp b/toonz/sources/toonzlib/studiopalettecmd.cpp index 8cf07e9..c8023ec 100644 --- a/toonz/sources/toonzlib/studiopalettecmd.cpp +++ b/toonz/sources/toonzlib/studiopalettecmd.cpp @@ -501,7 +501,11 @@ void StudioPaletteCmd::loadIntoCurrentPalette(TPaletteHandle *paletteHandle, // keep the color model path unchanged TFilePath oldRefImagePath = current->getRefImgPath(); + std::wstring oldGlobalName = current->getGlobalName(); current->assign(palette, true); + // keep global name unchanged + current->setGlobalName(oldGlobalName); + current->setDirtyFlag(true); current->setRefImgPath(oldRefImagePath); diff --git a/toonz/sources/toonzlib/toonzfolders.cpp b/toonz/sources/toonzlib/toonzfolders.cpp index ff09da0..a8ccd6b 100644 --- a/toonz/sources/toonzlib/toonzfolders.cpp +++ b/toonz/sources/toonzlib/toonzfolders.cpp @@ -3,20 +3,75 @@ #include "toonz/toonzfolders.h" #include "tsystem.h" #include "tenv.h" -//#include "appmainshell.h" #include "tconvert.h" #include "toonz/preferences.h" +#include using namespace TEnv; +//------------------------------------------------------------------- +namespace { +TFilePath getMyDocumentsPath() { + QString documentsPath = + QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation)[0]; + return TFilePath(documentsPath); +} + +// Desktop Path +TFilePath getDesktopPath() { + QString desktopPath = + QStandardPaths::standardLocations(QStandardPaths::DesktopLocation)[0]; + return TFilePath(desktopPath); +} +} +//------------------------------------------------------------------- + TFilePath ToonzFolder::getModulesDir() { return getProfileFolder() + "layouts"; } TFilePathSet ToonzFolder::getProjectsFolders() { - TFilePathSet fps = + int location = Preferences::instance()->getProjectRoot(); + QString path = Preferences::instance()->getCustomProjectRoot(); + TFilePathSet fps; + int projectPaths = Preferences::instance()->getProjectRoot(); + bool stuff = projectPaths & 0x08; + bool documents = projectPaths & 0x04; + bool desktop = projectPaths & 0x02; + bool custom = projectPaths & 0x01; + + // make sure at least something is there + if (!desktop && !custom && !documents) stuff = 1; + TFilePathSet tempFps = getSystemVarPathSetValue(getSystemVarPrefix() + "PROJECTS"); - if (fps.empty()) fps.push_back(TEnv::getStuffDir() + "Projects"); + if (stuff) { + for (TFilePath tempPath : tempFps) { + if (TSystem::doesExistFileOrLevel(TFilePath(tempPath))) { + fps.push_back(TFilePath(tempPath)); + } + } + if (tempFps.size() == 0) fps.push_back(TEnv::getStuffDir() + "Projects"); + } + if (documents) { + fps.push_back(getMyDocumentsPath() + "OpenToonz"); + if (!TSystem::doesExistFileOrLevel(getMyDocumentsPath() + "OpenToonz")) { + TSystem::mkDir(getMyDocumentsPath() + "OpenToonz"); + } + } + if (desktop) { + fps.push_back(getDesktopPath() + "OpenToonz"); + if (!TSystem::doesExistFileOrLevel(getDesktopPath() + "OpenToonz")) { + TSystem::mkDir(getDesktopPath() + "OpenToonz"); + } + } + if (custom) { + QStringList paths = path.split("**"); + for (QString tempPath : paths) { + if (TSystem::doesExistFileOrLevel(TFilePath(tempPath))) { + fps.push_back(TFilePath(tempPath)); + } + } + } return fps; } diff --git a/toonz/sources/toonzqt/dvdialog.cpp b/toonz/sources/toonzqt/dvdialog.cpp index 281586e..59cfbd8 100644 --- a/toonz/sources/toonzqt/dvdialog.cpp +++ b/toonz/sources/toonzqt/dvdialog.cpp @@ -729,6 +729,23 @@ void Dialog::addButtonBarWidget(QWidget *first, QWidget *second, } } +//----------------------------------------------------------------------------- +/*! Add four widget to the button part of dialog. +*/ +void Dialog::addButtonBarWidget(QWidget *first, QWidget *second, QWidget *third, + QWidget *fourth) { + first->setMinimumSize(65, 25); + second->setMinimumSize(65, 25); + third->setMinimumSize(65, 25); + assert(m_hasButton); + if (m_hasButton) { + m_buttonLayout->addWidget(first); + m_buttonLayout->addWidget(second); + m_buttonLayout->addWidget(third); + m_buttonLayout->addWidget(fourth); + } +} + //============================================================================= RadioButtonDialog::RadioButtonDialog(const QString &labelText, @@ -1060,6 +1077,65 @@ int DVGui::MsgBox(const QString &text, const QString &button1Text, //----------------------------------------------------------------------------- +int DVGui::MsgBox(const QString &text, const QString &button1Text, + const QString &button2Text, const QString &button3Text, + const QString &button4Text, int defaultButtonIndex, + QWidget *parent) { + Dialog dialog(parent, true); + dialog.setWindowFlags(dialog.windowFlags() | Qt::WindowStaysOnTopHint); + dialog.setAlignment(Qt::AlignLeft); + QString msgBoxTitle = getMsgBoxTitle(QUESTION); + dialog.setWindowTitle(msgBoxTitle); + + QLabel *mainTextLabel = new QLabel(text, &dialog); + QPixmap iconPixmap = getMsgBoxPixmap(QUESTION); + if (!iconPixmap.isNull()) { + QLabel *iconLabel = new QLabel(&dialog); + iconLabel->setPixmap(iconPixmap); + + QHBoxLayout *mainLayout = new QHBoxLayout; + mainLayout->addWidget(iconLabel); + mainLayout->addSpacing(16); + mainLayout->addWidget(mainTextLabel); + dialog.addLayout(mainLayout); + } else + dialog.addWidget(mainTextLabel); + + // ButtonGroup: is used only to retrieve the clicked button + QButtonGroup *buttonGroup = new QButtonGroup(&dialog); + + QPushButton *button1 = new QPushButton(button1Text, &dialog); + button1->setDefault(false); + if (defaultButtonIndex == 0) button1->setDefault(true); + dialog.addButtonBarWidget(button1); + buttonGroup->addButton(button1, 1); + + QPushButton *button2 = new QPushButton(button2Text, &dialog); + button2->setDefault(false); + if (defaultButtonIndex == 1) button2->setDefault(true); + dialog.addButtonBarWidget(button2); + buttonGroup->addButton(button2, 2); + + QPushButton *button3 = new QPushButton(button3Text, &dialog); + button3->setDefault(false); + if (defaultButtonIndex == 2) button3->setDefault(true); + dialog.addButtonBarWidget(button3); + buttonGroup->addButton(button3, 3); + + QPushButton *button4 = new QPushButton(button4Text, &dialog); + button4->setDefault(false); + if (defaultButtonIndex == 3) button4->setDefault(true); + dialog.addButtonBarWidget(button4); + buttonGroup->addButton(button4, 4); + + QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), &dialog, + SLOT(done(int))); + dialog.raise(); + return dialog.exec(); +} + +//----------------------------------------------------------------------------- + int DVGui::MsgBox(const QString &text, const QString &button1, const QString &button2, int defaultButtonIndex, QWidget *parent) { diff --git a/toonz/sources/toonzqt/flipconsole.cpp b/toonz/sources/toonzqt/flipconsole.cpp index 706bb6e..1caa5ac 100644 --- a/toonz/sources/toonzqt/flipconsole.cpp +++ b/toonz/sources/toonzqt/flipconsole.cpp @@ -1234,16 +1234,19 @@ void FlipConsole::createPlayToolBar(bool withCustomWidget) { if (m_gadgetsMask & eRed || m_gadgetsMask & eGRed) m_colorFilterSep = m_playToolBar->addSeparator(); - // Sound & Histogram - if (m_gadgetsMask & eSound || m_gadgetsMask & eHisto) { + // Sound & Histogram & Locator + if (m_gadgetsMask & eSound || m_gadgetsMask & eHisto || + m_gadgetsMask & eLocator) { if (m_gadgetsMask & eSound) { createButton(eSound, "sound", tr("&Soundtrack "), true); m_soundSep = m_playToolBar->addSeparator(); } - if (m_gadgetsMask & eHisto) { + if (m_gadgetsMask & eHisto) createButton(eHisto, "histograms", tr("&Histogram"), false); + if (m_gadgetsMask & eLocator) + createButton(eLocator, "locator", tr("&Locator"), false); + if (m_gadgetsMask & eHisto || m_gadgetsMask & eLocator) m_histoSep = m_playToolBar->addSeparator(); - } } if (m_gadgetsMask & eFilledRaster) { @@ -1572,6 +1575,7 @@ void FlipConsole::doButtonPressed(UINT button) { case eHisto: case eSaveImg: case eSave: + case eLocator: // nothing to do return; diff --git a/toonz/sources/toonzqt/menubarcommand.cpp b/toonz/sources/toonzqt/menubarcommand.cpp index 5e9612f..723cfda 100644 --- a/toonz/sources/toonzqt/menubarcommand.cpp +++ b/toonz/sources/toonzqt/menubarcommand.cpp @@ -279,7 +279,8 @@ int CommandManager::getKeyFromId(const char *id) { //--------------------------------------------------------- -void CommandManager::setShortcut(QAction *action, std::string shortcutString) { +void CommandManager::setShortcut(QAction *action, std::string shortcutString, + bool keepDefault) { QString shortcut = QString::fromStdString(shortcutString); std::string oldShortcutString = action->shortcut().toString().toStdString(); @@ -296,7 +297,7 @@ void CommandManager::setShortcut(QAction *action, std::string shortcutString) { if (node->m_type == ZoomCommandType && ks.count() > 1) { DVGui::warning( - QObject::tr("It is not possible to assing a shortcut with modifiers to " + QObject::tr("It is not possible to assign a shortcut with modifiers to " "the visualization commands.")); return; } @@ -328,7 +329,9 @@ void CommandManager::setShortcut(QAction *action, std::string shortcutString) { settings.beginGroup("shortcuts"); settings.setValue(QString::fromStdString(node->m_id), QString::fromStdString(shortcutString)); - if (oldActionId != "") settings.remove(oldActionId); + if (keepDefault) { + if (oldActionId != "") settings.remove(oldActionId); + } settings.endGroup(); } diff --git a/toonz/sources/toonzqt/paletteviewer.cpp b/toonz/sources/toonzqt/paletteviewer.cpp index faace8b..b7a59ea 100644 --- a/toonz/sources/toonzqt/paletteviewer.cpp +++ b/toonz/sources/toonzqt/paletteviewer.cpp @@ -911,10 +911,7 @@ void PaletteViewer::saveStudioPalette() { if (ret == 2 || ret == 0) return; sp->setPalette(fp, getPalette(), false); - question = "Do you want to update all linked styles in current scene ?"; - ret = DVGui::MsgBox(question, tr("Update"), tr("Don't Update"), 0); - if (ret == 1) - StudioPaletteCmd::updateAllLinkedStyles(m_paletteHandle, m_xsheetHandle); + StudioPaletteCmd::updateAllLinkedStyles(m_paletteHandle, m_xsheetHandle); palette->setDirtyFlag(false); } diff --git a/toonz/sources/toonzqt/paletteviewergui.cpp b/toonz/sources/toonzqt/paletteviewergui.cpp index 43f0e81..a692b71 100644 --- a/toonz/sources/toonzqt/paletteviewergui.cpp +++ b/toonz/sources/toonzqt/paletteviewergui.cpp @@ -454,7 +454,11 @@ void PageViewer::drawColorName(QPainter &p, QRect &nameRect, TColorStyle *style, name += " " + toQString(g.first) + ":" + QString::number(g.second); if (style->getFlags() != 0) name += "(autopaint)"; - p.drawText(nameRect.adjusted(8, 4, -6, -4), name); + TPoint pickedPos = style->getPickedPosition(); + if (pickedPos != TPoint()) + name += QString(" (%1,%2)").arg(pickedPos.x).arg(pickedPos.y); + + p.drawText(nameRect.adjusted(6, 4, -6, -4), name); QColor borderCol(getTextColor()); borderCol.setAlphaF(0.3); @@ -809,10 +813,23 @@ void PageViewer::paintEvent(QPaintEvent *e) { p.drawText(indexRect, Qt::AlignCenter, QString().setNum(styleIndex)); // draw "Autopaint for lines" indicator + int offset = 0; if (style->getFlags() != 0) { QRect aflRect(chipRect.bottomLeft() + QPoint(0, -14), QSize(12, 15)); p.drawRect(aflRect); p.drawText(aflRect, Qt::AlignCenter, "A"); + offset += 12; + } + + // draw "Picked Position" indicator (not show on small chip mode) + if (style->getPickedPosition() != TPoint() && m_viewMode != SmallChips) { + QRect ppRect(chipRect.bottomLeft() + QPoint(offset, -14), + QSize(12, 15)); + p.drawRect(ppRect); + QPoint markPos = ppRect.center() + QPoint(1, 0); + p.drawEllipse(markPos, 3, 3); + p.drawLine(markPos - QPoint(5, 0), markPos + QPoint(5, 0)); + p.drawLine(markPos - QPoint(0, 5), markPos + QPoint(0, 5)); } // revert font set @@ -1060,27 +1077,21 @@ void PageViewer::contextMenuEvent(QContextMenuEvent *event) { // remove links from studio palette if (m_viewType == LEVEL_PALETTE && m_styleSelection && - !m_styleSelection->isEmpty() && !isLocked) { + !m_styleSelection->isEmpty() && !isLocked && + m_styleSelection->hasLinkedStyle()) { menu.addSeparator(); - QAction *removeLinkAct = menu.addAction(tr("Remove Links")); - connect(removeLinkAct, SIGNAL(triggered()), this, SLOT(removeLink())); + QAction *toggleStyleLink = cmd->getAction("MI_ToggleLinkToStudioPalette"); + menu.addAction(toggleStyleLink); + QAction *removeStyleLink = + cmd->getAction("MI_RemoveReferenceToStudioPalette"); + menu.addAction(removeStyleLink); + QAction *getBackOriginalAct = + cmd->getAction("MI_GetColorFromStudioPalette"); + menu.addAction(getBackOriginalAct); } if (((indexPage == 0 && index > 0) || (indexPage > 0 && index >= 0)) && index < getChipCount() && !isLocked) { - // iwsw commented out temporarly - /* - wstring globalName = m_page->getStyle(index)->getGlobalName(); - if (m_viewType != STUDIO_PALETTE && - globalName != L"" && - (globalName[0] == L'-' || globalName[0] == L'+')) - { - createMenuAction(menu, "MI_ToggleLinkToStudioPalette", tr("Toggle - Link to Studio Palette"), "toggleLink()"); - createMenuAction(menu, "MI_RemoveReferenceToStudioPalette", - tr("Remove Reference to Studio Palette"), "eraseToggleLink()"); - } - */ if (pasteValueAct) pasteValueAct->setEnabled(true); if (pasteColorsAct) pasteColorsAct->setEnabled(true); @@ -1098,29 +1109,20 @@ void PageViewer::contextMenuEvent(QContextMenuEvent *event) { clearAct->setEnabled(false); } - // get color from the original studio palette - if (m_viewType == LEVEL_PALETTE && m_styleSelection && - !m_styleSelection->isEmpty() && !isLocked) { + if (m_page) { menu.addSeparator(); - QAction *getBackOriginalAct = - cmd->getAction("MI_GetColorFromStudioPalette"); - menu.addAction(getBackOriginalAct); + QAction *newStyle = menu.addAction(tr("New Style")); + connect(newStyle, SIGNAL(triggered()), SLOT(addNewColor())); + QAction *newPage = menu.addAction(tr("New Page")); + connect(newPage, SIGNAL(triggered()), SLOT(addNewPage())); } - // iwsw commented out temporarly /* - if (m_viewType != STUDIO_PALETTE) - { - menu.addSeparator(); + if (m_viewType != STUDIO_PALETTE) { menu.addAction(cmd->getAction(MI_EraseUnusedStyles)); } */ - if (m_page) { - QAction *newStyle = menu.addAction(tr("New Style")); - connect(newStyle, SIGNAL(triggered()), SLOT(addNewColor())); - QAction *newPage = menu.addAction(tr("New Page")); - connect(newPage, SIGNAL(triggered()), SLOT(addNewPage())); - } + menu.exec(event->globalPos()); } @@ -1408,25 +1410,6 @@ void PageViewer::onStyleRenamed() { } //----------------------------------------------------------------------------- -/*! Recall \b TStyleSelection::toggleLink() to current page style selection. -*/ -void PageViewer::toggleLink() { - if (!m_page || !m_styleSelection || m_styleSelection->isEmpty()) return; - m_styleSelection->toggleLink(); - update(); - emit changeWindowTitleSignal(); -} - -//----------------------------------------------------------------------------- -/*! Recall \b TStyleSelection::eraseToggleLink() to current page style - * selection. -*/ -void PageViewer::eraseToggleLink() { - if (!m_page || !m_styleSelection || m_styleSelection->isEmpty()) return; - m_styleSelection->eraseToggleLink(); -} - -//----------------------------------------------------------------------------- bool PageViewer::hasShortcut(int indexInPage) { if (!m_page) return false; @@ -1698,13 +1681,6 @@ void PageViewer::updateCommandLocks() { cmd->getAction("MI_BlendColors")->setEnabled(!isLocked); cmd->getAction("MI_PasteNames")->setEnabled(!isLocked); cmd->getAction("MI_GetColorFromStudioPalette")->setEnabled(!isLocked); -} - -//----------------------------------------------------------------------------- -/*! remove link and revert to the normal style -*/ -void PageViewer::removeLink() { - if (!m_page || !m_styleSelection || m_styleSelection->isEmpty()) return; - - if (m_styleSelection->removeLink()) emit changeWindowTitleSignal(); + cmd->getAction("MI_ToggleLinkToStudioPalette")->setEnabled(!isLocked); + cmd->getAction("MI_RemoveReferenceToStudioPalette")->setEnabled(!isLocked); } diff --git a/toonz/sources/toonzqt/studiopaletteviewer.cpp b/toonz/sources/toonzqt/studiopaletteviewer.cpp index 052335e..bb6b00e 100644 --- a/toonz/sources/toonzqt/studiopaletteviewer.cpp +++ b/toonz/sources/toonzqt/studiopaletteviewer.cpp @@ -497,6 +497,7 @@ void StudioPaletteTreeViewer::onCurrentItemChanged(QTreeWidgetItem *current, m_currentPalette = StudioPalette::instance()->getPalette(newPath, false); m_studioPaletteHandle->setPalette(m_currentPalette.getPointer()); m_studioPaletteHandle->notifyPaletteSwitched(); + StudioPaletteCmd::updateAllLinkedStyles(m_levelPaletteHandle, m_xsheetHandle); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonzqt/styleeditor.cpp b/toonz/sources/toonzqt/styleeditor.cpp index 107db3e..361b879 100644 --- a/toonz/sources/toonzqt/styleeditor.cpp +++ b/toonz/sources/toonzqt/styleeditor.cpp @@ -3060,9 +3060,13 @@ void StyleEditor::onStyleSwitched() { QString::fromStdWString(L" Palette : " + palette->getPaletteName()); // style name - statusText += QString::fromStdWString(L" | Style#"); + statusText += QString::fromStdWString(L" | #"); statusText += QString::number(styleIndex); statusText += QString::fromStdWString(L" : " + m_editedStyle->getName()); + TPoint pickedPos = m_editedStyle->getPickedPosition(); + if (pickedPos != TPoint()) + statusText += + QString(" (Picked from %1,%2)").arg(pickedPos.x).arg(pickedPos.y); m_statusLabel->setText(statusText); } else diff --git a/toonz/sources/toonzqt/styleselection.cpp b/toonz/sources/toonzqt/styleselection.cpp index 024ace0..99f9bb9 100644 --- a/toonz/sources/toonzqt/styleselection.cpp +++ b/toonz/sources/toonzqt/styleselection.cpp @@ -505,9 +505,14 @@ void TStyleSelection::enableCommands() { enableCommand(this, MI_PasteNames, &TStyleSelection::pasteStylesName); // available only for level palette - if (m_paletteHandle->getPalette()->getGlobalName() == L"") + if (m_paletteHandle->getPalette()->getGlobalName() == L"") { enableCommand(this, MI_GetColorFromStudioPalette, &TStyleSelection::getBackOriginalStyle); + enableCommand(this, MI_ToggleLinkToStudioPalette, + &TStyleSelection::toggleLink); + enableCommand(this, MI_RemoveReferenceToStudioPalette, + &TStyleSelection::removeLink); + } } enableCommand(this, MI_Clear, &TStyleSelection::deleteStyles); enableCommand(this, MI_EraseUnusedStyles, &TStyleSelection::eraseUnsedStyle); @@ -1408,14 +1413,15 @@ public: void TStyleSelection::toggleLink() { TPalette *palette = getPalette(); if (!palette || m_pageIndex < 0) return; + if (isEmpty() || palette->isLocked()) return; int n = m_styleIndicesInPage.size(); if (n <= 0) return; std::vector> oldColorStylesLinked; std::vector> newColorStylesLinked; - bool somethingHasBeenLinked = false; - + bool somethingHasBeenLinked = false; + bool somethingChanged = false; bool currentStyleIsInSelection = false; TPalette::Page *page = palette->getPage(m_pageIndex); @@ -1435,6 +1441,7 @@ void TStyleSelection::toggleLink() { name[0] = name[0] == L'-' ? L'+' : L'-'; cs->setGlobalName(name); if (name[0] == L'+') somethingHasBeenLinked = true; + somethingChanged = true; } undo->setColorStyle(index, oldCs, name); @@ -1442,6 +1449,13 @@ void TStyleSelection::toggleLink() { palette->getPage(m_pageIndex)->search(m_paletteHandle->getStyleIndex())) currentStyleIsInSelection = true; } + + // if nothing changed, do not set dirty flag, nor register undo + if (!somethingChanged) { + delete undo; + return; + } + if (somethingHasBeenLinked) StudioPalette::instance()->updateLinkedColors(palette); @@ -1460,6 +1474,7 @@ void TStyleSelection::toggleLink() { void TStyleSelection::eraseToggleLink() { TPalette *palette = getPalette(); if (!palette || m_pageIndex < 0) return; + if (isEmpty() || palette->isLocked()) return; int n = m_styleIndicesInPage.size(); if (n <= 0) return; @@ -1575,7 +1590,7 @@ public: int getSize() const override { return sizeof(*this); } QString getHistoryString() override { - return QObject::tr("Remove Link in Palette : %1") + return QObject::tr("Remove Reference in Palette : %1") .arg(QString::fromStdWString(m_palette->getPaletteName())); } int getHistoryType() override { return HistoryType::Palette; } @@ -1585,11 +1600,11 @@ public: /*! remove link from studio palette. Delete the global and the orginal names. * return true if something changed */ -bool TStyleSelection::removeLink() { +void TStyleSelection::removeLink() { TPalette *palette = getPalette(); - if (!palette || m_pageIndex < 0) return false; + if (!palette || m_pageIndex < 0) return; int n = m_styleIndicesInPage.size(); - if (n <= 0) return false; + if (n <= 0) return; TPalette::Page *page = palette->getPage(m_pageIndex); assert(page); @@ -1614,12 +1629,10 @@ bool TStyleSelection::removeLink() { } if (somethingChanged) { - palette->setDirtyFlag(true); + m_paletteHandle->notifyColorStyleChanged(false); TUndoManager::manager()->add(undo); } else delete undo; - - return somethingChanged; } //============================================================================= @@ -1781,3 +1794,26 @@ void TStyleSelection::getBackOriginalStyle() { } else delete undo; } + +//----------------------------------------------------------------------------- +/*! return true if there is at least one linked style in the selection +*/ + +bool TStyleSelection::hasLinkedStyle() { + TPalette *palette = getPalette(); + if (!palette || m_pageIndex < 0 || isEmpty()) return false; + if (m_styleIndicesInPage.size() <= 0) return false; + + TPalette::Page *page = palette->getPage(m_pageIndex); + assert(page); + + // for each selected style + for (std::set::iterator it = m_styleIndicesInPage.begin(); + it != m_styleIndicesInPage.end(); ++it) { + TColorStyle *cs = page->getStyle(*it); + std::wstring gname = cs->getGlobalName(); + // if the style has link, return true + if (gname != L"" && (gname[0] == L'-' || gname[0] == L'+')) return true; + } + return false; +}