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 #####
21 from bpy
.props
import (
29 from .ui_panels
import GP_PT_sidebarPanel
31 def get_addon_prefs():
33 addon_name
= os
.path
.splitext(__name__
)[0]
34 addon_prefs
= bpy
.context
.preferences
.addons
[addon_name
].preferences
37 from .timeline_scrub
import GPTS_timeline_settings
, draw_ts_pref
39 ## Addons Preferences Update Panel
40 def update_panel(self
, context
):
42 bpy
.utils
.unregister_class(GP_PT_sidebarPanel
)
45 GP_PT_sidebarPanel
.bl_category
= get_addon_prefs().category
46 bpy
.utils
.register_class(GP_PT_sidebarPanel
)
48 ## keymap binder for rotate canvas
49 def auto_rebind(self
, context
):
53 class GreasePencilAddonPrefs(bpy
.types
.AddonPreferences
):
54 bl_idname
= os
.path
.splitext(__name__
)[0] #'greasepencil-addon' ... __package__ ?
55 # bl_idname = __name__
57 ts
: PointerProperty(type=GPTS_timeline_settings
)
59 category
: StringProperty(
61 description
="Choose a name for the category of the panel",
62 default
="Grease Pencil",
65 pref_tabs
: EnumProperty(
66 items
=(('PREF', "Preferences", "Preferences properties of GP"),
67 ('TUTO', "Tutorial", "How to use the tool"),
68 # ('KEYMAP', "Keymap", "customise the default keymap"),
73 use_clic_drag
: BoolProperty(
74 name
='Use click drag directly on points',
75 description
="Change the active tool to 'tweak' during modal, Allow to direct clic-drag points of the box",
78 default_deform_type
: EnumProperty(
79 items
=(('KEY_LINEAR', "Linear (perspective mode)", "Linear interpolation, like corner deform / perspective tools of classic 2D", 'IPO_LINEAR',0),
80 ('KEY_BSPLINE', "Spline (smooth deform)", "Spline interpolation transformation\nBest when lattice is subdivided", 'IPO_CIRC',1),
82 name
='Starting Interpolation', default
='KEY_LINEAR', description
='Choose default interpolation when entering mode')
84 # About interpolation : https://docs.blender.org/manual/en/2.83/animation/shape_keys/shape_keys_panel.html#fig-interpolation-type
86 auto_swap_deform_type
: BoolProperty(
87 name
='Auto swap interpolation mode',
88 description
="Automatically set interpolation to 'spline' when subdividing lattice\n Back to 'linear' when",
91 ## rotate canvas variables
94 canvas_use_hud
: BoolProperty(
96 description
= "Display angle lines and angle value as text on viewport",
100 canvas_use_shortcut
: BoolProperty(
101 name
= "Use Default Shortcut",
102 description
= "Use default shortcut: mouse double-click + modifier",
106 mouse_click
: EnumProperty(
107 name
="Mouse button", description
="click on right/left/middle mouse button in combination with a modifier to trigger alignement",
108 default
='MIDDLEMOUSE',
110 ('RIGHTMOUSE', 'Right click', 'Use click on Right mouse button', 'MOUSE_RMB', 0),
111 ('LEFTMOUSE', 'Left click', 'Use click on Left mouse button', 'MOUSE_LMB', 1),
112 ('MIDDLEMOUSE', 'Mid click', 'Use click on Mid mouse button', 'MOUSE_MMB', 2),
116 use_shift
: BoolProperty(
117 name
= "combine with shift",
118 description
= "add shift",
122 use_alt
: BoolProperty(
123 name
= "combine with alt",
124 description
= "add alt",
128 use_ctrl
: BoolProperty(
129 name
= "combine with ctrl",
130 description
= "add ctrl",
134 def draw(self
, context
):
135 prefs
= get_addon_prefs()
137 # layout.use_property_split = True
138 row
= layout
.row(align
=True)
139 row
.prop(self
, "pref_tabs", expand
=True)
141 if self
.pref_tabs
== 'PREF':
145 row
= box
.row(align
=True)
146 row
.label(text
="Panel Category:")
147 row
.prop(self
, "category", text
="")
151 box
.label(text
='Box Deform:')
152 box
.prop(self
, "use_clic_drag")
154 box
.prop(self
, "default_deform_type")
155 box
.label(text
="Deformer type can be changed during modal with 'M' key, this is for default behavior", icon
='INFO')
157 box
.prop(self
, "auto_swap_deform_type")
158 box
.label(text
="Once 'M' is hit, auto swap is desactivated to stay in your chosen mode", icon
='INFO')
162 box
.label(text
='Rotate canvas:')
164 box
.prop(self
, "canvas_use_shortcut", text
='Bind Shortcuts')
166 if self
.canvas_use_shortcut
:
169 row
.label(text
="(Auto rebind when changing shortcut)")#icon=""
170 # row.operator("prefs.rebind_shortcut", text='Bind/Rebind shortcuts', icon='FILE_REFRESH')#EVENT_SPACEKEY
171 row
= box
.row(align
= True)
172 row
.prop(self
, "use_ctrl", text
='Ctrl')#, expand=True
173 row
.prop(self
, "use_alt", text
='Alt')#, expand=True
174 row
.prop(self
, "use_shift", text
='Shift')#, expand=True
175 row
.prop(self
, "mouse_click",text
='')#expand=True
177 if not self
.use_ctrl
and not self
.use_alt
and not self
.use_shift
:
178 box
.label(text
="Choose at least one modifier to combine with click (default: Ctrl+Alt)", icon
="ERROR")# INFO
181 box
.label(text
="No hotkey has been set automatically. Following operators needs to be set manually:", icon
="ERROR")
182 box
.label(text
="view3d.rotate_canvas")
183 box
.prop(self
, 'canvas_use_hud')
187 draw_ts_pref(prefs
.ts
, box
)
189 if self
.pref_tabs
== 'TUTO':
191 #**Behavior from context mode**
192 col
= layout
.column()
193 col
.label(text
='Box Deform Tool')
194 col
.label(text
="Usage:", icon
='MOD_LATTICE')
195 col
.label(text
="Use the shortcut 'Ctrl+T' in available modes (listed below)")
196 col
.label(text
="The lattice box is generated facing your view (be sure to face canvas if you want to stay on it)")
197 col
.label(text
="Use shortcuts below to deform (a help will be displayed in the topbar)")
200 col
.label(text
="Shortcuts:", icon
='HAND')
201 col
.label(text
="Spacebar / Enter : Confirm")
202 col
.label(text
="Delete / Backspace / Tab(twice) / Ctrl+T : Cancel")
203 col
.label(text
="M : Toggle between Linear and Spline mode at any moment")
204 col
.label(text
="1-9 top row number : Subdivide the box")
205 col
.label(text
="Ctrl + arrows-keys : Subdivide the box incrementally in individual X/Y axis")
208 col
.label(text
="Modes and deformation target:", icon
='PIVOT_BOUNDBOX')
209 col
.label(text
="- Object mode : The whole GP object is deformed (including all frames)")
210 col
.label(text
="- GPencil Edit mode : Deform Selected points")
211 col
.label(text
="- Gpencil Paint : Deform last Strokes")
212 # col.label(text="- Lattice edit : Revive the modal after a ctrl+Z")
215 col
.label(text
="Notes:", icon
='TEXT')
216 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.")
217 col
.label(text
="- A cancel warning will be displayed the first time you hit Tab")
220 ### rotate canvas keymap
224 def register_keymaps():
225 pref
= get_addon_prefs()
226 if not pref
.canvas_use_shortcut
:
228 addon
= bpy
.context
.window_manager
.keyconfigs
.addon
230 km
= addon
.keymaps
.new(name
= "3D View", space_type
= "VIEW_3D")
232 if 'view3d.rotate_canvas' not in km
.keymap_items
:
233 km
= addon
.keymaps
.new(name
='3D View', space_type
='VIEW_3D')
234 kmi
= km
.keymap_items
.new('view3d.rotate_canvas',
235 type=pref
.mouse_click
, value
="PRESS", alt
=pref
.use_alt
, ctrl
=pref
.use_ctrl
, shift
=pref
.use_shift
, any
=False)
237 addon_keymaps
.append((km
, kmi
))
239 def unregister_keymaps():
240 for km
, kmi
in addon_keymaps
:
241 km
.keymap_items
.remove(kmi
)
242 addon_keymaps
.clear()
249 GPTS_timeline_settings
,
250 GreasePencilAddonPrefs
,
255 bpy
.utils
.register_class(cls
)
256 # Force box deform running to false
257 bpy
.context
.preferences
.addons
[os
.path
.splitext(__name__
)[0]].preferences
.boxdeform_running
= False
262 for cls
in reversed(classes
):
263 bpy
.utils
.unregister_class(cls
)