Cleanup: quiet character escape warnings
[blender-addons.git] / greasepencil_tools / prefs.py
blob11d3d0be73b5d03fe0e9c81fcac9bd14dff678e4
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 import bpy
20 import os
21 from bpy.props import (
22 BoolProperty,
23 EnumProperty,
24 StringProperty,
25 PointerProperty,
26 FloatProperty,
27 # IntProperty,
30 from .ui_panels import GP_PT_sidebarPanel
32 def get_addon_prefs():
33 import os
34 addon_name = os.path.splitext(__name__)[0]
35 addon_prefs = bpy.context.preferences.addons[addon_name].preferences
36 return (addon_prefs)
38 from .timeline_scrub import GPTS_timeline_settings, draw_ts_pref
40 ## Addons Preferences Update Panel
41 def update_panel(self, context):
42 try:
43 bpy.utils.unregister_class(GP_PT_sidebarPanel)
44 except:
45 pass
46 GP_PT_sidebarPanel.bl_category = get_addon_prefs().category
47 bpy.utils.register_class(GP_PT_sidebarPanel)
49 ## keymap binder for rotate canvas
50 def auto_rebind(self, context):
51 unregister_keymaps()
52 register_keymaps()
54 class GreasePencilAddonPrefs(bpy.types.AddonPreferences):
55 bl_idname = os.path.splitext(__name__)[0] #'greasepencil-addon' ... __package__ ?
56 # bl_idname = __name__
58 ts: PointerProperty(type=GPTS_timeline_settings)
60 category : StringProperty(
61 name="Category",
62 description="Choose a name for the category of the panel",
63 default="Grease Pencil",
64 update=update_panel)
66 # --- props
67 use_clic_drag : BoolProperty(
68 name='Use click drag directly on points',
69 description="Change the active tool to 'tweak' during modal, Allow to direct clic-drag points of the box",
70 default=True)
72 default_deform_type : EnumProperty(
73 items=(('KEY_LINEAR', "Linear (perspective mode)", "Linear interpolation, like corner deform / perspective tools of classic 2D", 'IPO_LINEAR',0),
74 ('KEY_BSPLINE', "Spline (smooth deform)", "Spline interpolation transformation\nBest when lattice is subdivided", 'IPO_CIRC',1),
76 name='Starting Interpolation', default='KEY_LINEAR', description='Choose default interpolation when entering mode')
78 # About interpolation : https://docs.blender.org/manual/en/2.83/animation/shape_keys/shape_keys_panel.html#fig-interpolation-type
80 auto_swap_deform_type : BoolProperty(
81 name='Auto swap interpolation mode',
82 description="Automatically set interpolation to 'spline' when subdividing lattice\n Back to 'linear' when",
83 default=True)
85 ## rotate canvas variables
87 ## Use HUD
88 canvas_use_hud: BoolProperty(
89 name = "Use Hud",
90 description = "Display angle lines and angle value as text on viewport",
91 default = False)
93 canvas_use_view_center: BoolProperty(
94 name = "Rotate From View Center In Camera",
95 description = "Rotate from view center in camera view, Else rotate from camera center",
96 default = True)
98 ## Canvas rotate
99 canvas_use_shortcut: BoolProperty(
100 name = "Use Default Shortcut",
101 description = "Use default shortcut: mouse double-click + modifier",
102 default = True,
103 update=auto_rebind)
105 mouse_click : EnumProperty(
106 name="Mouse button", description="click on right/left/middle mouse button in combination with a modifier to trigger alignement",
107 default='MIDDLEMOUSE',
108 items=(
109 ('RIGHTMOUSE', 'Right click', 'Use click on Right mouse button', 'MOUSE_RMB', 0),
110 ('LEFTMOUSE', 'Left click', 'Use click on Left mouse button', 'MOUSE_LMB', 1),
111 ('MIDDLEMOUSE', 'Mid click', 'Use click on Mid mouse button', 'MOUSE_MMB', 2),
113 update=auto_rebind)
115 use_shift: BoolProperty(
116 name = "combine with shift",
117 description = "add shift",
118 default = False,
119 update=auto_rebind)
121 use_alt: BoolProperty(
122 name = "combine with alt",
123 description = "add alt",
124 default = True,
125 update=auto_rebind)
127 use_ctrl: BoolProperty(
128 name = "combine with ctrl",
129 description = "add ctrl",
130 default = True,
131 update=auto_rebind)
133 rc_angle_step: FloatProperty(
134 name="Angle Steps",
135 description="Step the rotation using this angle when using rotate canvas step modifier",
136 default=0.2617993877991494, # 15
137 min=0.01745329238474369, # 1
138 max=3.1415927410125732, # 180
139 soft_min=0.01745329238474369, # 1
140 soft_max=1.5707963705062866, # 90
141 step=10, precision=1, subtype='ANGLE', unit='ROTATION')
143 def draw(self, context):
144 prefs = get_addon_prefs()
145 layout = self.layout
146 # layout.use_property_split = True
147 row= layout.row(align=True)
149 ## TAB CATEGORY
150 box = layout.box()
151 row = box.row(align=True)
152 row.label(text="Panel Category:")
153 row.prop(self, "category", text="")
155 ## BOX DEFORM
156 box = layout.box()
157 row = box.row(align=True)
158 row.label(text='Box Deform:')
159 row.operator("wm.call_menu", text="", icon='QUESTION').name = "GPT_MT_box_deform_doc"
160 box.prop(self, "use_clic_drag")
162 box.prop(self, "default_deform_type")
163 box.label(text="Deformer type can be changed during modal with 'M' key, this is for default behavior", icon='INFO')
165 box.prop(self, "auto_swap_deform_type")
166 box.label(text="Once 'M' is hit, auto swap is desactivated to stay in your chosen mode", icon='INFO')
168 ## ROTATE CANVAS
169 box = layout.box()
170 box.label(text='Rotate canvas:')
172 box.prop(self, "canvas_use_shortcut", text='Bind Shortcuts')
174 if self.canvas_use_shortcut:
176 row = box.row()
177 row.label(text="(Auto rebind when changing shortcut)")#icon=""
178 # row.operator("prefs.rebind_shortcut", text='Bind/Rebind shortcuts', icon='FILE_REFRESH')#EVENT_SPACEKEY
179 row = box.row(align = True)
180 row.prop(self, "use_ctrl", text='Ctrl')#, expand=True
181 row.prop(self, "use_alt", text='Alt')#, expand=True
182 row.prop(self, "use_shift", text='Shift')#, expand=True
183 row.prop(self, "mouse_click",text='')#expand=True
185 if not self.use_ctrl and not self.use_alt and not self.use_shift:
186 box.label(text="Choose at least one modifier to combine with click (default: Ctrl+Alt)", icon="ERROR")# INFO
188 if not all((self.use_ctrl, self.use_alt, self.use_shift)):
189 row = box.row(align = True)
190 snap_key_list = []
191 if not self.use_ctrl:
192 snap_key_list.append('Ctrl')
193 if not self.use_shift:
194 snap_key_list.append('Shift')
195 if not self.use_alt:
196 snap_key_list.append('Alt')
198 row.label(text=f"Step rotation with: {' or '.join(snap_key_list)}", icon='DRIVER_ROTATIONAL_DIFFERENCE')
199 row.prop(self, "rc_angle_step", text='Angle Steps')
202 else:
203 box.label(text="No hotkey has been set automatically. Following operators needs to be set manually:", icon="ERROR")
204 box.label(text="view3d.rotate_canvas")
205 box.prop(self, 'canvas_use_view_center')
206 box.prop(self, 'canvas_use_hud')
208 ## SCRUB TIMELINE
209 box = layout.box()
210 draw_ts_pref(prefs.ts, box)
214 class GPT_MT_box_deform_doc(bpy.types.Menu):
215 # bl_idname = "OBJECT_MT_custom_menu"
216 bl_label = "Box Deform Infos Sheet"
218 def draw(self, context):
219 layout = self.layout
220 # call another menu
221 #layout.operator("wm.call_menu", text="Unwrap").name = "VIEW3D_MT_uv_map"
222 #**Behavior from context mode**
223 col = layout.column()
224 col.label(text='Box Deform Tool')
225 col.label(text="Usage:", icon='MOD_LATTICE')
226 col.label(text="Use the shortcut 'Ctrl+T' in available modes (listed below)")
227 col.label(text="The lattice box is generated facing your view (be sure to face canvas if you want to stay on it)")
228 col.label(text="Use shortcuts below to deform (a help will be displayed in the topbar)")
230 col.separator()
231 col.label(text="Shortcuts:", icon='HAND')
232 col.label(text="Spacebar / Enter : Confirm")
233 col.label(text="Shift + Spacebar / Enter : Confirm and let the lattice in place")
234 col.label(text="Delete / Backspace / Tab(twice) / Ctrl+T : Cancel")
235 col.label(text="M : Toggle between Linear and Spline mode at any moment")
236 col.label(text="1-9 top row number : Subdivide the box")
237 col.label(text="Ctrl + arrows-keys : Subdivide the box incrementally in individual X/Y axis")
239 col.separator()
240 col.label(text="Modes and deformation target:", icon='PIVOT_BOUNDBOX')
241 col.label(text="- Object mode : The whole GP object is deformed (including all frames)")
242 col.label(text="- GPencil Edit mode : Deform Selected points")
243 col.label(text="- Gpencil Paint : Deform last Strokes")
244 # col.label(text="- Lattice edit : Revive the modal after a ctrl+Z")
246 col.separator()
247 col.label(text="Notes:", icon='TEXT')
248 col.label(text="- If you return in box deform after applying (with a ctrl+Z), you need to hit 'Ctrl+T' again to revive the modal.")
249 col.label(text="- A cancel warning will be displayed the first time you hit Tab")
251 ### rotate canvas keymap
253 addon_keymaps = []
254 def register_keymaps():
255 pref = get_addon_prefs()
256 if not pref.canvas_use_shortcut:
257 return
258 addon = bpy.context.window_manager.keyconfigs.addon
260 km = addon.keymaps.new(name = "3D View", space_type = "VIEW_3D")
262 if 'view3d.rotate_canvas' not in km.keymap_items:
263 km = addon.keymaps.new(name='3D View', space_type='VIEW_3D')
264 kmi = km.keymap_items.new('view3d.rotate_canvas',
265 type=pref.mouse_click, value="PRESS", alt=pref.use_alt, ctrl=pref.use_ctrl, shift=pref.use_shift, any=False)
267 addon_keymaps.append((km, kmi))
269 def unregister_keymaps():
270 for km, kmi in addon_keymaps:
271 km.keymap_items.remove(kmi)
272 addon_keymaps.clear()
275 ### REGISTER ---
277 classes = (
278 GPTS_timeline_settings,
279 GPT_MT_box_deform_doc,
280 GreasePencilAddonPrefs,
283 def register():
284 for cls in classes:
285 bpy.utils.register_class(cls)
286 # Force box deform running to false
287 bpy.context.preferences.addons[os.path.splitext(__name__)[0]].preferences.boxdeform_running = False
288 register_keymaps()
290 def unregister():
291 unregister_keymaps()
292 for cls in reversed(classes):
293 bpy.utils.unregister_class(cls)