1 # SPDX-License-Identifier: GPL-2.0-or-later
5 from bpy
.props
import (
14 from .ui_panels
import GP_PT_sidebarPanel
16 def get_addon_prefs():
18 addon_name
= os
.path
.splitext(__name__
)[0]
19 addon_prefs
= bpy
.context
.preferences
.addons
[addon_name
].preferences
22 from .timeline_scrub
import GPTS_timeline_settings
, draw_ts_pref
24 ## Addons Preferences Update Panel
25 def update_panel(self
, context
):
27 bpy
.utils
.unregister_class(GP_PT_sidebarPanel
)
30 GP_PT_sidebarPanel
.bl_category
= get_addon_prefs().category
31 bpy
.utils
.register_class(GP_PT_sidebarPanel
)
33 ## keymap binder for rotate canvas
34 def auto_rebind(self
, context
):
38 class GreasePencilAddonPrefs(bpy
.types
.AddonPreferences
):
39 bl_idname
= os
.path
.splitext(__name__
)[0] #'greasepencil-addon' ... __package__ ?
40 # bl_idname = __name__
42 ts
: PointerProperty(type=GPTS_timeline_settings
)
44 category
: StringProperty(
46 description
="Choose a name for the category of the panel",
47 default
="Grease Pencil",
51 use_clic_drag
: BoolProperty(
52 name
='Use click drag directly on points',
53 description
="Change the active tool to 'tweak' during modal, Allow to direct clic-drag points of the box",
56 default_deform_type
: EnumProperty(
57 items
=(('KEY_LINEAR', "Linear (perspective mode)", "Linear interpolation, like corner deform / perspective tools of classic 2D", 'IPO_LINEAR',0),
58 ('KEY_BSPLINE', "Spline (smooth deform)", "Spline interpolation transformation\nBest when lattice is subdivided", 'IPO_CIRC',1),
60 name
='Starting Interpolation', default
='KEY_LINEAR', description
='Choose default interpolation when entering mode')
62 # About interpolation : https://docs.blender.org/manual/en/2.83/animation/shape_keys/shape_keys_panel.html#fig-interpolation-type
64 auto_swap_deform_type
: BoolProperty(
65 name
='Auto swap interpolation mode',
66 description
="Automatically set interpolation to 'spline' when subdividing lattice\n Back to 'linear' when",
69 ## rotate canvas variables
72 canvas_use_hud
: BoolProperty(
74 description
= "Display angle lines and angle value as text on viewport",
77 canvas_use_view_center
: BoolProperty(
78 name
= "Rotate From View Center In Camera",
79 description
= "Rotate from view center in camera view, Else rotate from camera center",
83 canvas_use_shortcut
: BoolProperty(
84 name
= "Use Default Shortcut",
85 description
= "Use default shortcut: mouse double-click + modifier",
89 mouse_click
: EnumProperty(
90 name
="Mouse button", description
="click on right/left/middle mouse button in combination with a modifier to trigger alignment",
91 default
='MIDDLEMOUSE',
93 ('RIGHTMOUSE', 'Right click', 'Use click on Right mouse button', 'MOUSE_RMB', 0),
94 ('LEFTMOUSE', 'Left click', 'Use click on Left mouse button', 'MOUSE_LMB', 1),
95 ('MIDDLEMOUSE', 'Mid click', 'Use click on Mid mouse button', 'MOUSE_MMB', 2),
99 use_shift
: BoolProperty(
100 name
= "combine with shift",
101 description
= "add shift",
105 use_alt
: BoolProperty(
106 name
= "combine with alt",
107 description
= "add alt",
111 use_ctrl
: BoolProperty(
112 name
= "combine with ctrl",
113 description
= "add ctrl",
117 rc_angle_step
: FloatProperty(
119 description
="Step the rotation using this angle when using rotate canvas step modifier",
120 default
=0.2617993877991494, # 15
121 min=0.01745329238474369, # 1
122 max=3.1415927410125732, # 180
123 soft_min
=0.01745329238474369, # 1
124 soft_max
=1.5707963705062866, # 90
125 step
=10, precision
=1, subtype
='ANGLE', unit
='ROTATION')
127 def draw(self
, context
):
128 prefs
= get_addon_prefs()
130 # layout.use_property_split = True
131 row
= layout
.row(align
=True)
135 row
= box
.row(align
=True)
136 row
.label(text
="Panel Category:")
137 row
.prop(self
, "category", text
="")
141 row
= box
.row(align
=True)
142 row
.label(text
='Box Deform:')
143 row
.operator("wm.call_menu", text
="", icon
='QUESTION').name
= "GPT_MT_box_deform_doc"
144 box
.prop(self
, "use_clic_drag")
146 box
.prop(self
, "default_deform_type")
147 box
.label(text
="Deformer type can be changed during modal with 'M' key, this is for default behavior", icon
='INFO')
149 box
.prop(self
, "auto_swap_deform_type")
150 box
.label(text
="Once 'M' is hit, auto swap is deactivated to stay in your chosen mode", icon
='INFO')
154 box
.label(text
='Rotate canvas:')
156 box
.prop(self
, "canvas_use_shortcut", text
='Bind Shortcuts')
158 if self
.canvas_use_shortcut
:
161 row
.label(text
="(Auto rebind when changing shortcut)")#icon=""
162 # row.operator("prefs.rebind_shortcut", text='Bind/Rebind shortcuts', icon='FILE_REFRESH')#EVENT_SPACEKEY
163 row
= box
.row(align
= True)
164 row
.prop(self
, "use_ctrl", text
='Ctrl')#, expand=True
165 row
.prop(self
, "use_alt", text
='Alt')#, expand=True
166 row
.prop(self
, "use_shift", text
='Shift')#, expand=True
167 row
.prop(self
, "mouse_click",text
='')#expand=True
169 if not self
.use_ctrl
and not self
.use_alt
and not self
.use_shift
:
170 box
.label(text
="Choose at least one modifier to combine with click (default: Ctrl+Alt)", icon
="ERROR")# INFO
172 if not all((self
.use_ctrl
, self
.use_alt
, self
.use_shift
)):
173 row
= box
.row(align
= True)
175 if not self
.use_ctrl
:
176 snap_key_list
.append('Ctrl')
177 if not self
.use_shift
:
178 snap_key_list
.append('Shift')
180 snap_key_list
.append('Alt')
182 row
.label(text
=f
"Step rotation with: {' or '.join(snap_key_list)}", icon
='DRIVER_ROTATIONAL_DIFFERENCE')
183 row
.prop(self
, "rc_angle_step", text
='Angle Steps')
187 box
.label(text
="No hotkey has been set automatically. Following operators needs to be set manually:", icon
="ERROR")
188 box
.label(text
="view3d.rotate_canvas")
189 box
.prop(self
, 'canvas_use_view_center')
190 box
.prop(self
, 'canvas_use_hud')
194 draw_ts_pref(prefs
.ts
, box
)
198 class GPT_MT_box_deform_doc(bpy
.types
.Menu
):
199 # bl_idname = "OBJECT_MT_custom_menu"
200 bl_label
= "Box Deform Infos Sheet"
202 def draw(self
, context
):
205 #layout.operator("wm.call_menu", text="Unwrap").name = "VIEW3D_MT_uv_map"
206 #**Behavior from context mode**
207 col
= layout
.column()
208 col
.label(text
='Box Deform Tool')
209 col
.label(text
="Usage:", icon
='MOD_LATTICE')
210 col
.label(text
="Use the shortcut 'Ctrl+T' in available modes (listed below)")
211 col
.label(text
="The lattice box is generated facing your view (be sure to face canvas if you want to stay on it)")
212 col
.label(text
="Use shortcuts below to deform (a help will be displayed in the topbar)")
215 col
.label(text
="Shortcuts:", icon
='HAND')
216 col
.label(text
="Spacebar / Enter : Confirm")
217 col
.label(text
="Shift + Spacebar / Enter : Confirm and let the lattice in place")
218 col
.label(text
="Delete / Backspace / Tab(twice) / Ctrl+T : Cancel")
219 col
.label(text
="M : Toggle between Linear and Spline mode at any moment")
220 col
.label(text
="1-9 top row number : Subdivide the box")
221 col
.label(text
="Ctrl + arrows-keys : Subdivide the box incrementally in individual X/Y axis")
224 col
.label(text
="Modes and deformation target:", icon
='PIVOT_BOUNDBOX')
225 col
.label(text
="- Object mode : The whole GP object is deformed (including all frames)")
226 col
.label(text
="- GPencil Edit mode : Deform Selected points")
227 col
.label(text
="- Gpencil Paint : Deform last Strokes")
228 # col.label(text="- Lattice edit : Revive the modal after a ctrl+Z")
231 col
.label(text
="Notes:", icon
='TEXT')
232 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.")
233 col
.label(text
="- A cancel warning will be displayed the first time you hit Tab")
235 ### rotate canvas keymap
238 def register_keymaps():
239 pref
= get_addon_prefs()
240 if not pref
.canvas_use_shortcut
:
242 addon
= bpy
.context
.window_manager
.keyconfigs
.addon
244 km
= addon
.keymaps
.new(name
= "3D View", space_type
= "VIEW_3D")
246 if 'view3d.rotate_canvas' not in km
.keymap_items
:
247 km
= addon
.keymaps
.new(name
='3D View', space_type
='VIEW_3D')
248 kmi
= km
.keymap_items
.new('view3d.rotate_canvas',
249 type=pref
.mouse_click
, value
="PRESS", alt
=pref
.use_alt
, ctrl
=pref
.use_ctrl
, shift
=pref
.use_shift
, any
=False)
251 addon_keymaps
.append((km
, kmi
))
253 def unregister_keymaps():
254 for km
, kmi
in addon_keymaps
:
255 km
.keymap_items
.remove(kmi
)
256 addon_keymaps
.clear()
262 GPTS_timeline_settings
,
263 GPT_MT_box_deform_doc
,
264 GreasePencilAddonPrefs
,
269 bpy
.utils
.register_class(cls
)
270 # Force box deform running to false
271 bpy
.context
.preferences
.addons
[os
.path
.splitext(__name__
)[0]].preferences
.boxdeform_running
= False
276 for cls
in reversed(classes
):
277 bpy
.utils
.unregister_class(cls
)