2021-01-10 16:47:17 +01:00
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
bl_info = {
2021-01-19 19:49:16 +01:00
" name " : " GP toolbox " ,
2021-01-10 16:47:17 +01:00
" description " : " Set of tools for Grease Pencil in animation production " ,
" author " : " Samuel Bernou " ,
2021-06-14 17:41:41 +02:00
" version " : ( 1 , 4 , 3 ) ,
2021-01-10 16:47:17 +01:00
" blender " : ( 2 , 91 , 0 ) ,
2021-06-05 01:20:35 +02:00
" location " : " Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties " ,
2021-01-10 16:47:17 +01:00
" warning " : " " ,
" doc_url " : " https://gitlab.com/autour-de-minuit/blender/gp_toolbox " ,
2021-01-14 23:36:05 +01:00
" tracker_url " : " https://gitlab.com/autour-de-minuit/blender/gp_toolbox/-/issues " ,
2021-01-10 16:47:17 +01:00
" category " : " 3D View " ,
}
from . import addon_updater_ops
from . utils import *
from . functions import *
## GMIC
from . GP_guided_colorize import GP_colorize
## direct tools
from . import OP_breakdowner
from . import OP_temp_cutter
from . import OP_playblast_bg
from . import OP_playblast
from . import OP_helpers
2021-01-19 01:11:18 +01:00
from . import OP_keyframe_jump
2021-01-10 16:47:17 +01:00
from . import OP_cursor_snap_canvas
from . import OP_palettes
2021-06-14 17:41:41 +02:00
from . import OP_brushes
2021-01-10 16:47:17 +01:00
from . import OP_file_checker
from . import OP_render
from . import OP_copy_paste
2021-05-04 23:17:19 +02:00
from . import OP_realign
2021-05-09 01:26:37 +02:00
from . import OP_depth_move
2021-05-24 17:06:10 +02:00
from . import OP_key_duplicate_send
2021-05-30 23:51:18 +02:00
from . import handler_draw_cam
2021-01-10 16:47:17 +01:00
from . import keymaps
from . OP_pseudo_tint import GPT_OT_auto_tint_gp_layers
from . import UI_tools
from . properties import GP_PG_ToolsSettings
from bpy . props import ( FloatProperty ,
BoolProperty ,
EnumProperty ,
StringProperty ,
IntProperty )
import bpy
from bpy . app . handlers import persistent
from pathlib import Path
# from .eyedrop import EyeDropper
# from .properties import load_icons,remove_icons
### prefs
# def set_palette_path(self, context):
# print('value set')
# self.palette_path = Path(bpy.path.abspath(self["palette_path"])).as_posix()
2021-03-07 00:39:32 +01:00
@persistent
def remap_relative ( dummy ) :
2021-05-05 18:33:34 +02:00
# try:
2021-03-07 00:39:32 +01:00
all_path = [ lib for lib in bpy . utils . blend_paths ( local = True ) ]
bpy . ops . file . make_paths_relative ( )
for i , lib in enumerate ( bpy . utils . blend_paths ( local = True ) ) :
if all_path [ i ] != lib :
print ( ' Remapped: ' , all_path [ i ] , ' \n >> ' , lib )
2021-05-05 18:33:34 +02:00
# except Exception as e:
# print(e)
2021-03-07 00:39:32 +01:00
def remap_on_save_update ( self , context ) :
pref = get_addon_prefs ( )
if pref . use_relative_remap_on_save :
if not ' remap_relative ' in [ hand . __name__ for hand in bpy . app . handlers . save_pre ] :
bpy . app . handlers . save_pre . append ( remap_relative )
else :
if ' remap_relative ' in [ hand . __name__ for hand in bpy . app . handlers . save_pre ] :
bpy . app . handlers . save_pre . remove ( remap_relative )
2021-01-10 16:47:17 +01:00
class GPTB_prefs ( bpy . types . AddonPreferences ) :
bl_idname = __name__
## tabs
2021-03-07 00:39:32 +01:00
pref_tabs : EnumProperty (
2021-01-10 16:47:17 +01:00
items = ( ( ' PREF ' , " Preferences " , " Change some preferences of the modal " ) ,
( ' MAN_OPS ' , " Operator " , " Operator to add Manually " ) ,
# ('TUTO', "Tutorial", "How to use the tool"),
( ' UPDATE ' , " Update " , " Check and apply updates " ) ,
# ('KEYMAP', "Keymap", "customise the default keymap"),
) ,
default = ' PREF ' )
## addon pref updater props
auto_check_update : BoolProperty (
name = " Auto-check for Update " ,
description = " If enabled, auto-check for updates using an interval " ,
default = False ,
)
updater_intrval_months : IntProperty (
name = ' Months ' ,
description = " Number of months between checking for updates " ,
default = 0 ,
min = 0
)
updater_intrval_days : IntProperty (
name = ' Days ' ,
description = " Number of days between checking for updates " ,
default = 7 ,
min = 0 ,
max = 31
)
updater_intrval_hours : IntProperty (
name = ' Hours ' ,
description = " Number of hours between checking for updates " ,
default = 0 ,
min = 0 ,
max = 23
)
updater_intrval_minutes : IntProperty (
name = ' Minutes ' ,
description = " Number of minutes between checking for updates " ,
default = 0 ,
min = 0 ,
max = 59
)
## addon prefs
## Project preferences
# subtype (string) – Enumerator in ['FILE_PATH', 'DIR_PATH', 'FILE_NAME', 'BYTE_STRING', 'PASSWORD', 'NONE'].
## fps
2021-03-07 00:39:32 +01:00
use_relative_remap_on_save : BoolProperty (
name = " Relative Remap On Save " ,
description = " Always remap all external path to relative when saving \n Need blender restart if changed " ,
2021-05-05 18:33:34 +02:00
default = False ,
2021-03-07 00:39:32 +01:00
update = remap_on_save_update
)
2021-01-10 16:47:17 +01:00
fps : IntProperty (
name = ' Frame Rate ' ,
description = " Fps of the project, Used to conform the file when you use Check file operator " ,
default = 25 ,
min = 1 ,
max = 10000
)
## output settings for automated renders
output_parent_level = IntProperty (
name = ' Parent level ' ,
description = " Go up in folder to define a render path relative to the file in upper directotys " ,
default = 0 ,
min = 0 ,
max = 20
)
output_path : StringProperty (
name = " Output path " ,
description = " Path relative to blend to place render " ,
default = " //render " , maxlen = 0 , subtype = ' DIR_PATH ' )
separator : StringProperty (
name = " Namespace separator " ,
description = " Character delimiter to use for detecting namespace (prefix), default is ' _ ' , space if nothing specified " ,
default = " _ " , maxlen = 0 , subtype = ' NONE ' )
palette_path : StringProperty (
name = " Palettes directory " ,
description = " Path to palette containing palette.json files to save and load " ,
default = " // " , maxlen = 0 , subtype = ' DIR_PATH ' ) #, update = set_palette_path
2021-06-14 17:41:41 +02:00
brush_path : StringProperty (
name = " Brushes directory " ,
description = " Path to brushes containing the blends holding the brushes " ,
default = " // " , maxlen = 0 , subtype = ' DIR_PATH ' ) #, update = set_palette_path
2021-01-10 16:47:17 +01:00
## Playblast prefs
playblast_auto_play : BoolProperty (
name = " Playblast auto play " ,
description = " Open rendered playblast when finished " ,
default = True ,
)
playblast_auto_open_folder : BoolProperty (
name = " Playblast auto open location " ,
description = " Open folder of rendered playblast when finished " ,
default = False ,
)
## default active tool to use
select_active_tool : EnumProperty (
name = " Default selection tool " , description = " Active tool to set when launching check fix scene " ,
default = ' builtin.select_lasso ' ,
items = (
( ' none ' , ' Dont change ' , ' Let the current active tool without change ' , 0 ) , #'MOUSE_RMB'
( ' builtin.select ' , ' Select tweak ' , ' Use active select tweak active tool ' , 1 ) , #'MOUSE_RMB'
( ' builtin.select_box ' , ' Select box ' , ' Use active select box active tool ' , 2 ) , #'MOUSE_LMB'
( ' builtin.select_circle ' , ' Select circle ' , ' Use active select circle active tool ' , 3 ) , #'MOUSE_MMB'
( ' builtin.select_lasso ' , ' Select lasso ' , ' Use active select lasso active tool ' , 4 ) , #'MOUSE_MMB'
) )
## render settings
render_obj_exclusion : StringProperty (
name = " GP obj exclude filter " ,
description = " List comma separated words to exclude from render list " ,
default = " old,rough,trash,test " ) #, subtype='FILE_PATH')
render_res_x : IntProperty (
name = ' Resolution X ' ,
description = " Resolution on X " ,
default = 2048 ,
min = 1 ,
max = 10000
)
render_res_y : IntProperty (
name = ' Resolution Y ' ,
description = " Resolution on Y " ,
default = 1080 ,
min = 1 ,
max = 10000
)
2021-01-19 01:11:18 +01:00
## KF jumper
kfj_use_shortcut : BoolProperty (
name = " Use Keyframe Jump Shortcut " ,
2021-05-02 23:14:38 +02:00
description = " Auto bind shotcut for keyframe jump (else you can bind manually using ' screen.gp_keyframe_jump ' id_name) " ,
2021-01-19 01:11:18 +01:00
default = True )
kfj_prev_keycode : StringProperty (
name = " Jump Prev Shortcut " ,
description = " Shortcut to trigger previous keyframe jump " ,
default = " F5 " )
kfj_prev_shift : BoolProperty (
name = " Shift " ,
description = " add shift " ,
default = False )
kfj_prev_alt : BoolProperty (
name = " Alt " ,
description = " add alt " ,
default = False )
kfj_prev_ctrl : BoolProperty (
name = " combine with ctrl " ,
description = " add ctrl " ,
default = False )
kfj_next_keycode : StringProperty (
name = " Jump Next Shortcut " ,
description = " Shortcut to trigger keyframe jump " ,
default = " F6 " )
kfj_next_shift : BoolProperty (
name = " Shift " ,
description = " add shift " ,
default = False )
kfj_next_alt : BoolProperty (
name = " Alt " ,
description = " add alt " ,
default = False )
kfj_next_ctrl : BoolProperty (
name = " combine with ctrl " ,
description = " add ctrl " ,
default = False )
2021-01-10 16:47:17 +01:00
## Temp cutter
# temp_cutter_use_shortcut: BoolProperty(
# name = "Use temp cutter Shortcut",
# description = "Auto assign shortcut for temp_cutter",
# default = True)
def draw ( self , context ) :
layout = self . layout ## random color
# layout.use_property_split = True
row = layout . row ( align = True )
row . prop ( self , " pref_tabs " , expand = True )
if self . pref_tabs == ' PREF ' :
box = layout . box ( )
box . label ( text = ' Project settings ' )
## Render
# box.label(text='Render option:')
box . prop ( self , ' fps ' )
row = box . row ( align = True )
2021-03-07 00:39:32 +01:00
row . label ( text = ' Render Resolution ' )
row . prop ( self , ' render_res_x ' , text = ' Width ' )
row . prop ( self , ' render_res_y ' , text = ' Height ' )
2021-01-10 16:47:17 +01:00
## Palette
2021-06-14 17:41:41 +02:00
box . label ( text = ' Project folders: ' )
2021-01-10 16:47:17 +01:00
box . prop ( self , ' palette_path ' )
2021-06-14 17:41:41 +02:00
box . prop ( self , ' brush_path ' )
2021-01-10 16:47:17 +01:00
## render output
box . prop ( self , ' output_path ' )
2021-03-07 00:39:32 +01:00
box . prop ( self , ' use_relative_remap_on_save ' )
2021-01-10 16:47:17 +01:00
### TODO add render settings
# layout.separator()## Playblast
box = layout . box ( )
box . label ( text = ' Playblast options: ' )
box . prop ( self , ' playblast_auto_play ' )
box . prop ( self , ' playblast_auto_open_folder ' )
2021-01-19 01:11:18 +01:00
# box.separator()## Keyframe jumper
box = layout . box ( )
box . label ( text = ' Keyframe Jump option: ' )
box . prop ( self , " kfj_use_shortcut " , text = ' Bind shortcuts ' )
if self . kfj_use_shortcut :
prompt = ' [TYPE SHORTCUT TO USE (can be with modifiers)] '
if self . kfj_prev_keycode :
mods = ' + ' . join ( [ m for m , b in [ ( ' Ctrl ' , self . kfj_prev_ctrl ) , ( ' Shift ' , self . kfj_prev_shift ) , ( ' Alt ' , self . kfj_prev_alt ) ] if b ] )
text = f ' { mods } + { self . kfj_prev_keycode } ' if mods else self . kfj_prev_keycode
text = f ' Jump Keyframe Prev: { text } (Click to change) '
else :
text = prompt
ops = box . operator ( ' prefs.shortcut_rebinder ' , text = text , icon = ' FILE_REFRESH ' )
ops . s_keycode = ' kfj_prev_keycode '
ops . s_ctrl = ' kfj_prev_ctrl '
ops . s_shift = ' kfj_prev_shift '
ops . s_alt = ' kfj_prev_alt '
if self . kfj_next_keycode :
mods = ' + ' . join ( [ m for m , b in [ ( ' Ctrl ' , self . kfj_next_ctrl ) , ( ' Shift ' , self . kfj_next_shift ) , ( ' Alt ' , self . kfj_next_alt ) ] if b ] )
text = f ' { mods } + { self . kfj_next_keycode } ' if mods else self . kfj_next_keycode
text = f ' Jump Keyframe Next: { text } (Click to change) '
else :
text = prompt
ops = box . operator ( ' prefs.shortcut_rebinder ' , text = text , icon = ' FILE_REFRESH ' )
ops . s_keycode = ' kfj_next_keycode '
ops . s_ctrl = ' kfj_next_ctrl '
ops . s_shift = ' kfj_next_shift '
ops . s_alt = ' kfj_next_alt '
else :
box . label ( text = " No Jump hotkey auto set. Following operators needs to be set manually " , icon = " ERROR " )
box . label ( text = " screen.gp_keyframe_jump - preferably in ' screen ' category to jump from any editor " )
2021-01-10 16:47:17 +01:00
## Active tool
box = layout . box ( )
box . label ( text = ' Autofix check button options: ' )
box . prop ( self , " select_active_tool " , icon = ' RESTRICT_SELECT_OFF ' )
box . prop ( self , " render_obj_exclusion " , icon = ' FILTER ' ) #
2021-01-19 19:49:16 +01:00
## random color character separator
box = layout . box ( )
box . label ( text = ' Random color options: ' )
box . prop ( self , ' separator ' )
2021-01-10 16:47:17 +01:00
if self . pref_tabs == ' MAN_OPS ' :
# layout.separator()## notes
# layout.label(text='Notes:')
2021-03-31 01:38:17 +02:00
layout . label ( text = ' Following operators ID have to be set manually in keymap if needed : ' )
2021-01-10 16:47:17 +01:00
## keyframe jump
box = layout . box ( )
box . label ( text = ' GP keyframe jump (consider only GP keyframe, multiple options available at setup) ' )
row = box . row ( )
row . label ( text = ' screen.gp_keyframe_jump ' )
row . operator ( ' wm.copytext ' , icon = ' COPYDOWN ' ) . text = ' screen.gp_keyframe_jump '
# layout.separator()
## Snap cursor to GP
box = layout . box ( )
box . label ( text = ' Snap cursor to GP canvas (if not autoset) ' )
row = box . row ( )
row . label ( text = ' Look for default 3d snap operators by searching " view3d.cursor3d " ' )
row . operator ( ' wm.copytext ' , text = ' Copy " view3d.cursor3d " ' , icon = ' COPYDOWN ' ) . text = ' view3d.cursor3d '
row = box . row ( )
row . label ( text = ' Replace wanted by " view3d.cusor_snap " ' )
row . operator ( ' wm.copytext ' , text = ' Copy " view3d.cusor_snap " ' , icon = ' COPYDOWN ' ) . text = ' view3d.cusor_snap '
box . label ( text = ' Or just create a new shortcut using cursor_snap ' )
2021-03-31 01:38:17 +02:00
## Clear keyframe
box = layout . box ( )
box . label ( text = ' Clear active frame (delete all strokes without deleting the frame) ' )
row = box . row ( )
row . label ( text = ' gp.clear_active_frame ' )
row . operator ( ' wm.copytext ' , icon = ' COPYDOWN ' ) . text = ' gp.clear_active_frame '
2021-01-10 16:47:17 +01:00
## user prefs
box = layout . box ( )
box . label ( text = ' Note: You can access user pref file and startup file in config folder ' )
box . operator ( " wm.path_open " , text = ' Open config location ' ) . filepath = bpy . utils . user_resource ( ' CONFIG ' )
if self . pref_tabs == ' UPDATE ' :
addon_updater_ops . update_settings_ui ( self , context )
### --- REGISTER ---
# class GP_PG_ToolsSettings(bpy.types.PropertyGroup) :
# autotint_offset = bpy.props.IntProperty(name="Tint hue offset", description="offset the tint by this value for better color", default=0, min=-5000, max=5000, soft_min=-999, soft_max=999, step=1)#, subtype='PERCENTAGE'
classes = (
GPTB_prefs ,
GP_PG_ToolsSettings ,
GPT_OT_auto_tint_gp_layers ,
)
# register, unregister = bpy.utils.register_classes_factory(classes)
def register ( ) :
addon_updater_ops . register ( bl_info )
for cls in classes :
bpy . utils . register_class ( cls )
OP_helpers . register ( )
2021-01-19 01:11:18 +01:00
OP_keyframe_jump . register ( )
2021-01-10 16:47:17 +01:00
OP_file_checker . register ( )
OP_breakdowner . register ( )
OP_temp_cutter . register ( )
GP_colorize . register ( ) ## GP_guided_colorize.
OP_playblast_bg . register ( )
OP_playblast . register ( )
OP_palettes . register ( )
2021-06-14 17:41:41 +02:00
OP_brushes . register ( )
2021-01-10 16:47:17 +01:00
OP_cursor_snap_canvas . register ( )
OP_render . register ( )
OP_copy_paste . register ( )
2021-05-04 23:17:19 +02:00
OP_realign . register ( )
2021-05-09 01:26:37 +02:00
OP_depth_move . register ( )
2021-05-24 17:06:10 +02:00
OP_key_duplicate_send . register ( )
2021-05-30 23:51:18 +02:00
handler_draw_cam . register ( )
2021-01-10 16:47:17 +01:00
UI_tools . register ( )
keymaps . register ( )
bpy . types . Scene . gptoolprops = bpy . props . PointerProperty ( type = GP_PG_ToolsSettings )
2021-03-07 00:39:32 +01:00
# add handler (if option is on)
if get_addon_prefs ( ) . use_relative_remap_on_save :
if not ' remap_relative ' in [ hand . __name__ for hand in bpy . app . handlers . save_pre ] :
bpy . app . handlers . save_pre . append ( remap_relative )
2021-01-10 16:47:17 +01:00
def unregister ( ) :
2021-03-07 00:39:32 +01:00
# remove handler
if ' remap_relative ' in [ hand . __name__ for hand in bpy . app . handlers . save_pre ] :
bpy . app . handlers . save_pre . remove ( remap_relative )
2021-01-10 16:47:17 +01:00
keymaps . unregister ( )
addon_updater_ops . unregister ( )
for cls in reversed ( classes ) :
bpy . utils . unregister_class ( cls )
UI_tools . unregister ( )
2021-05-30 23:51:18 +02:00
handler_draw_cam . unregister ( )
2021-05-24 17:06:10 +02:00
OP_key_duplicate_send . unregister ( )
2021-05-09 01:26:37 +02:00
OP_depth_move . unregister ( )
2021-05-04 23:17:19 +02:00
OP_realign . unregister ( )
2021-01-10 16:47:17 +01:00
OP_copy_paste . unregister ( )
OP_render . unregister ( )
OP_cursor_snap_canvas . unregister ( )
2021-06-14 17:41:41 +02:00
OP_brushes . unregister ( )
2021-01-10 16:47:17 +01:00
OP_palettes . unregister ( )
OP_file_checker . unregister ( )
OP_helpers . unregister ( )
2021-01-19 01:11:18 +01:00
OP_keyframe_jump . unregister ( )
2021-01-10 16:47:17 +01:00
OP_breakdowner . unregister ( )
OP_temp_cutter . unregister ( )
GP_colorize . unregister ( ) ## GP_guided_colorize.
OP_playblast_bg . unregister ( )
OP_playblast . unregister ( )
del bpy . types . Scene . gptoolprops
if __name__ == " __main__ " :
register ( )