-
Notifications
You must be signed in to change notification settings - Fork 8
/
prefs.py
310 lines (250 loc) · 12 KB
/
prefs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# SPDX-FileCopyrightText: 2020-2023 Blender Foundation
#
# SPDX-License-Identifier: GPL-3.0-or-later
import bpy
import os
from bpy.props import (
BoolProperty,
EnumProperty,
StringProperty,
PointerProperty,
FloatProperty,
# IntProperty,
)
from .ui_panels import GP_PT_sidebarPanel
def get_addon_prefs():
import os
addon_name = os.path.splitext(__name__)[0]
addon_prefs = bpy.context.preferences.addons[addon_name].preferences
return (addon_prefs)
from .timeline_scrub import GPTS_timeline_settings, draw_ts_pref
from .layer_navigator import GPNAV_layer_navigator_settings, draw_nav_pref
## Addons Preferences Update Panel
def update_panel(self, context):
try:
bpy.utils.unregister_class(GP_PT_sidebarPanel)
except:
pass
GP_PT_sidebarPanel.bl_category = get_addon_prefs().category
bpy.utils.register_class(GP_PT_sidebarPanel)
## keymap binder for rotate canvas
def auto_rebind(self, context):
unregister_keymaps()
register_keymaps()
class GreasePencilAddonPrefs(bpy.types.AddonPreferences):
bl_idname = os.path.splitext(__name__)[0] #__package__
ts: PointerProperty(type=GPTS_timeline_settings)
nav: PointerProperty(type=GPNAV_layer_navigator_settings)
category : StringProperty(
name="Category",
description="Choose a name for the category of the panel",
default="Grease Pencil",
update=update_panel)
## Tool tab
pref_tab : EnumProperty(
name="Preference Tool Tab", description="Choose tool preferences to display",
default='canvas_rotate',
items=(
('canvas_rotate', 'Rotate Canvas', 'Canvas Rotate tool shortcut and prefs', 0),
('box_deform', 'Box Deform', 'Box Deform tool prefs', 1),
('timeline_scrub', 'Timeline Scrub', 'Timeline Scrub tool shortcut and prefs', 2),
('layer_navigator', 'Layer Navigator', 'Layer Navigation tool shortcut and prefs', 3),
),
)
# --- props
use_clic_drag : BoolProperty(
name='Use click drag directly on points',
description="Change the active tool to 'tweak' during modal, Allow to direct clic-drag points of the box",
default=True)
default_deform_type : EnumProperty(
items=(('KEY_LINEAR', "Linear (perspective mode)", "Linear interpolation, like corner deform / perspective tools of classic 2D", 'IPO_LINEAR',0),
('KEY_BSPLINE', "Spline (smooth deform)", "Spline interpolation transformation\nBest when lattice is subdivided", 'IPO_CIRC',1),
),
name='Starting Interpolation', default='KEY_LINEAR', description='Choose default interpolation when entering mode')
# About interpolation : https://docs.blender.org/manual/en/2.83/animation/shape_keys/shape_keys_panel.html#fig-interpolation-type
auto_swap_deform_type : BoolProperty(
name='Auto swap interpolation mode',
description="Automatically set interpolation to 'spline' when subdividing lattice\n Back to 'linear' when",
default=True)
## rotate canvas variables
## Use HUD
canvas_use_hud: BoolProperty(
name = "Use Hud",
description = "Display angle lines and angle value as text on viewport",
default = False)
canvas_use_view_center: BoolProperty(
name = "Rotate From View Center In Camera",
description = "Rotate from view center in camera view, Else rotate from camera center",
default = True)
## Canvas rotate
canvas_use_shortcut: BoolProperty(
name = "Use Default Shortcut",
description = "Use default shortcut: mouse double-click + modifier",
default = True,
update=auto_rebind)
mouse_click : EnumProperty(
name="Mouse button", description="Click on chosen mouse button in combination with a modifier to trigger alignment",
default='MIDDLEMOUSE',
items=(
('RIGHTMOUSE', 'Right click', 'Use Right mouse button', 'MOUSE_RMB', 0),
('LEFTMOUSE', 'Left click', 'Use Left mouse button', 'MOUSE_LMB', 1),
('MIDDLEMOUSE', 'Mid click', 'Use Mid mouse button', 'MOUSE_MMB', 2),
('BUTTON4MOUSE', 'Mouse Button 4', 'Use mouse button 4 (previous)', 'EVENT_MOUSE_4', 3),
('BUTTON5MOUSE', 'Mouse Button 5', 'Use mouse button 5 (next)', 'EVENT_MOUSE_5', 4),
),
update=auto_rebind)
use_shift: BoolProperty(
name = "combine with shift",
description = "add shift",
default = False,
update=auto_rebind)
use_alt: BoolProperty(
name = "combine with alt",
description = "add alt",
default = True,
update=auto_rebind)
use_ctrl: BoolProperty(
name = "combine with ctrl",
description = "add ctrl",
default = True,
update=auto_rebind)
rc_angle_step: FloatProperty(
name="Angle Steps",
description="Step the rotation using this angle when using rotate canvas step modifier",
default=0.2617993877991494, # 15
min=0.01745329238474369, # 1
max=3.1415927410125732, # 180
soft_min=0.01745329238474369, # 1
soft_max=1.5707963705062866, # 90
step=10, precision=1, subtype='ANGLE', unit='ROTATION')
def draw(self, context):
prefs = get_addon_prefs()
layout = self.layout
# layout.use_property_split = True
row= layout.row(align=True)
## TAB CATEGORY
box = layout.box()
row = box.row(align=True)
row.label(text="Panel Category:")
row.prop(self, "category", text="")
row = layout.row(align=True)
row.prop(self, "pref_tab", expand=True)
if self.pref_tab == 'box_deform':
## BOX DEFORM
box = layout.box()
row = box.row(align=True)
row.label(text='Box Deform:')
row.operator("wm.call_menu", text="", icon='QUESTION').name = "GPT_MT_box_deform_doc"
box.prop(self, "use_clic_drag")
box.prop(self, "default_deform_type")
box.label(text="Deformer type can be changed during modal with 'M' key, this is for default behavior", icon='INFO')
box.prop(self, "auto_swap_deform_type")
box.label(text="Once 'M' is hit, auto swap is deactivated to stay in your chosen mode", icon='INFO')
if self.pref_tab == 'canvas_rotate':
## ROTATE CANVAS
box = layout.box()
box.label(text='Rotate Canvas:')
box.prop(self, "canvas_use_shortcut", text='Bind Shortcuts')
if self.canvas_use_shortcut:
row = box.row()
row.label(text="(Auto rebind when changing shortcut)")#icon=""
# row.operator("prefs.rebind_shortcut", text='Bind/Rebind shortcuts', icon='FILE_REFRESH')#EVENT_SPACEKEY
row = box.row(align = True)
row.prop(self, "use_ctrl", text='Ctrl')#, expand=True
row.prop(self, "use_alt", text='Alt')#, expand=True
row.prop(self, "use_shift", text='Shift')#, expand=True
row.prop(self, "mouse_click",text='')#expand=True
if not self.use_ctrl and not self.use_alt and not self.use_shift:
box.label(text="Choose at least one modifier to combine with click (default: Ctrl+Alt)", icon="ERROR")# INFO
if not all((self.use_ctrl, self.use_alt, self.use_shift)):
row = box.row(align = True)
snap_key_list = []
if not self.use_ctrl:
snap_key_list.append('Ctrl')
if not self.use_shift:
snap_key_list.append('Shift')
if not self.use_alt:
snap_key_list.append('Alt')
row.label(text=f"Step rotation with: {' or '.join(snap_key_list)}", icon='DRIVER_ROTATIONAL_DIFFERENCE')
row.prop(self, "rc_angle_step", text='Angle Steps')
else:
box.label(text="No hotkey has been set automatically. Following operators needs to be set manually:", icon="ERROR")
box.label(text="view3d.rotate_canvas")
box.prop(self, 'canvas_use_view_center')
box.prop(self, 'canvas_use_hud')
if self.pref_tab == 'timeline_scrub':
## SCRUB TIMELINE
box = layout.box()
draw_ts_pref(prefs.ts, box)
if self.pref_tab == 'layer_navigator':
## LAYER NAVIGATOR
box = layout.box()
draw_nav_pref(prefs.nav, box)
class GPT_MT_box_deform_doc(bpy.types.Menu):
# bl_idname = "OBJECT_MT_custom_menu"
bl_label = "Box Deform Infos Sheet"
def draw(self, context):
layout = self.layout
# call another menu
#layout.operator("wm.call_menu", text="Unwrap").name = "VIEW3D_MT_uv_map"
#**Behavior from context mode**
col = layout.column()
col.label(text='Box Deform Tool')
col.label(text="Usage:", icon='MOD_LATTICE')
col.label(text="Use the shortcut 'Ctrl+T' in available modes (listed below)")
col.label(text="The lattice box is generated facing your view (be sure to face canvas if you want to stay on it)")
col.label(text="Use shortcuts below to deform (a help will be displayed in the topbar)")
col.separator()
col.label(text="Shortcuts:", icon='HAND')
col.label(text="Spacebar / Enter : Confirm")
col.label(text="Shift + Spacebar / Enter : Confirm and let the lattice in place")
col.label(text="Delete / Backspace / Tab(twice) / Ctrl+T : Cancel")
col.label(text="M : Toggle between Linear and Spline mode at any moment")
col.label(text="1-9 top row number : Subdivide the box")
col.label(text="Ctrl + arrows-keys : Subdivide the box incrementally in individual X/Y axis")
col.separator()
col.label(text="Modes and deformation target:", icon='PIVOT_BOUNDBOX')
col.label(text="- Object mode : The whole GP object is deformed (including all frames)")
col.label(text="- GPencil Edit mode : Deform Selected points")
col.label(text="- Gpencil Paint : Deform last Strokes")
# col.label(text="- Lattice edit : Revive the modal after a ctrl+Z")
col.separator()
col.label(text="Notes:", icon='TEXT')
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.")
col.label(text="- A cancel warning will be displayed the first time you hit Tab")
### rotate canvas keymap
addon_keymaps = []
def register_keymaps():
pref = get_addon_prefs()
if not pref.canvas_use_shortcut:
return
kc = bpy.context.window_manager.keyconfigs.addon
if kc is None:
return
km = kc.keymaps.new(name = "3D View", space_type = "VIEW_3D")
if 'view3d.rotate_canvas' not in km.keymap_items:
km = kc.keymaps.new(name='3D View', space_type='VIEW_3D')
kmi = km.keymap_items.new('view3d.rotate_canvas',
type=pref.mouse_click, value="PRESS", alt=pref.use_alt, ctrl=pref.use_ctrl, shift=pref.use_shift, any=False)
addon_keymaps.append((km, kmi))
def unregister_keymaps():
for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi)
addon_keymaps.clear()
### REGISTER ---
classes = (
GPTS_timeline_settings,
GPNAV_layer_navigator_settings,
GPT_MT_box_deform_doc,
GreasePencilAddonPrefs,
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
# Force box deform running to false
bpy.context.preferences.addons[os.path.splitext(__name__)[0]].preferences.boxdeform_running = False
register_keymaps()
def unregister():
unregister_keymaps()
for cls in reversed(classes):
bpy.utils.unregister_class(cls)