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 #####
22 from bpy.types import Menu, UIList
23 from bpy.app.translations import pgettext_iface as iface_
26 def gpencil_stroke_placement_settings(context, layout):
27 if context.space_data.type == 'VIEW_3D':
28 propname = "gpencil_stroke_placement_view3d"
29 elif context.space_data.type == 'SEQUENCE_EDITOR':
30 propname = "gpencil_stroke_placement_sequencer_preview"
31 elif context.space_data.type == 'IMAGE_EDITOR':
32 propname = "gpencil_stroke_placement_image_editor"
34 propname = "gpencil_stroke_placement_view2d"
36 ts = context.tool_settings
38 col = layout.column(align=True)
40 col.label(text="Stroke Placement:")
42 row = col.row(align=True)
43 row.prop_enum(ts, propname, 'VIEW')
44 row.prop_enum(ts, propname, 'CURSOR')
46 if context.space_data.type == 'VIEW_3D':
47 row = col.row(align=True)
48 row.prop_enum(ts, propname, 'SURFACE')
49 row.prop_enum(ts, propname, 'STROKE')
51 row = col.row(align=False)
52 row.active = getattr(ts, propname) in {'SURFACE', 'STROKE'}
53 row.prop(ts, "use_gpencil_stroke_endpoints")
56 def gpencil_active_brush_settings_simple(context, layout):
57 brush = context.active_gpencil_brush
60 col.label("Active Brush: ")
62 row = col.row(align=True)
63 row.operator_context = 'EXEC_REGION_WIN'
64 row.operator_menu_enum("gpencil.brush_change", "brush", text="", icon='BRUSH_DATA')
65 row.prop(brush, "name", text="")
67 col.prop(brush, "line_width", slider=True)
68 row = col.row(align=True)
69 row.prop(brush, "use_random_pressure", text='', icon='RNDCURVE')
70 row.prop(brush, "pen_sensitivity_factor", slider=True)
71 row.prop(brush, "use_pressure", text='', icon='STYLUS_PRESSURE')
72 row = col.row(align=True)
73 row.prop(brush, "use_random_strength", text='', icon='RNDCURVE')
74 row.prop(brush, "strength", slider=True)
75 row.prop(brush, "use_strength_pressure", text='', icon='STYLUS_PRESSURE')
76 row = col.row(align=True)
77 row.prop(brush, "jitter", slider=True)
78 row.prop(brush, "use_jitter_pressure", text='', icon='STYLUS_PRESSURE')
80 row.prop(brush, "angle", slider=True)
81 row.prop(brush, "angle_factor", text="Factor", slider=True)
84 class GreasePencilDrawingToolsPanel:
86 # bl_space_type = 'IMAGE_EDITOR'
87 bl_label = "Grease Pencil"
88 bl_category = "Grease Pencil"
89 bl_region_type = 'TOOLS'
92 def draw(self, context):
95 is_3d_view = context.space_data.type == 'VIEW_3D'
96 is_clip_editor = context.space_data.type == 'CLIP_EDITOR'
98 col = layout.column(align=True)
100 col.label(text="Draw:")
101 row = col.row(align=True)
102 row.operator("gpencil.draw", icon='GREASEPENCIL', text="Draw").mode = 'DRAW'
103 row.operator("gpencil.draw", icon='FORCE_CURVE', text="Erase").mode = 'ERASER' # XXX: Needs a dedicated icon
105 row = col.row(align=True)
106 row.operator("gpencil.draw", icon='LINE_DATA', text="Line").mode = 'DRAW_STRAIGHT'
107 row.operator("gpencil.draw", icon='MESH_DATA', text="Poly").mode = 'DRAW_POLY'
109 sub = col.column(align=True)
110 sub.prop(context.tool_settings, "use_gpencil_additive_drawing", text="Additive Drawing")
111 sub.prop(context.tool_settings, "use_gpencil_continuous_drawing", text="Continuous Drawing")
112 sub.prop(context.tool_settings, "use_gpencil_draw_onback", text="Draw on Back")
117 if context.space_data.type in {'VIEW_3D', 'CLIP_EDITOR'}:
119 col.label("Data Source:")
120 row = col.row(align=True)
122 row.prop(context.tool_settings, "grease_pencil_source", expand=True)
124 row.prop(context.space_data, "grease_pencil_source", expand=True)
129 gpencil_stroke_placement_settings(context, col)
131 gpd = context.gpencil_data
133 if gpd and not is_3d_view:
137 col = layout.column(align=True)
138 col.prop(gpd, "use_stroke_edit_mode", text="Enable Editing", icon='EDIT', toggle=True)
144 col.label(text="Tools:")
145 col.operator_menu_enum("gpencil.convert", text="Convert to Geometry...", property="type")
146 col.operator("view3d.ruler")
149 class GreasePencilStrokeEditPanel:
151 # bl_space_type = 'IMAGE_EDITOR'
152 bl_label = "Edit Strokes"
153 bl_category = "Grease Pencil"
154 bl_region_type = 'TOOLS'
155 bl_options = {'DEFAULT_CLOSED'}
158 def poll(cls, context):
159 if context.gpencil_data is None:
162 gpd = context.gpencil_data
163 return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
166 def draw(self, context):
169 is_3d_view = context.space_data.type == 'VIEW_3D'
172 layout.label(text="Select:")
173 col = layout.column(align=True)
174 col.operator("gpencil.select_all", text="Select All")
175 col.operator("gpencil.select_border")
176 col.operator("gpencil.select_circle")
180 col = layout.column(align=True)
181 col.operator("gpencil.select_linked")
182 col.operator("gpencil.select_more")
183 col.operator("gpencil.select_less")
184 col.operator("gpencil.palettecolor_select")
186 layout.label(text="Edit:")
187 row = layout.row(align=True)
188 row.operator("gpencil.copy", text="Copy")
189 row.operator("gpencil.paste", text="Paste").type = 'COPY'
190 row.operator("gpencil.paste", text="Paste & Merge").type = 'MERGE'
192 col = layout.column(align=True)
193 col.operator("gpencil.delete")
194 col.operator("gpencil.duplicate_move", text="Duplicate")
196 col.operator("gpencil.stroke_cyclical_set", text="Toggle Cyclic").type = 'TOGGLE'
201 col = layout.column(align=True)
202 col.operator("transform.translate") # icon='MAN_TRANS'
203 col.operator("transform.rotate") # icon='MAN_ROT'
204 col.operator("transform.resize", text="Scale") # icon='MAN_SCALE'
208 col = layout.column(align=True)
209 col.operator("transform.bend", text="Bend")
210 col.operator("transform.mirror", text="Mirror")
211 col.operator("transform.shear", text="Shear")
212 col.operator("transform.tosphere", text="To Sphere")
215 col = layout.column(align=True)
216 col.operator_menu_enum("gpencil.stroke_arrange", text="Arrange Strokes...", property="direction")
217 col.operator("gpencil.stroke_change_color", text="Move to Color")
221 col = layout.column(align=True)
222 col.operator("gpencil.interpolate", text="Interpolate")
223 col.operator("gpencil.interpolate_sequence", text="Sequence")
224 settings = context.tool_settings.gpencil_sculpt
225 col.prop(settings, "interpolate_all_layers")
226 col.prop(settings, "interpolate_selected_only")
229 col = layout.column(align=True)
230 col.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
231 col.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
232 col.operator("gpencil.stroke_flip", text="Flip Direction")
234 gpd = context.gpencil_data
236 col.prop(gpd, "show_stroke_direction", text="Show Directions")
240 layout.operator("gpencil.reproject")
243 class GreasePencilBrushPanel:
245 # bl_space_type = 'IMAGE_EDITOR'
246 bl_label = "Drawing Brushes"
247 bl_category = "Grease Pencil"
248 bl_region_type = 'TOOLS'
251 def draw(self, context):
256 ts = context.scene.tool_settings
257 if len(ts.gpencil_brushes) >= 2:
261 col.template_list("GPENCIL_UL_brush", "", ts, "gpencil_brushes", ts.gpencil_brushes, "active_index", rows=brows)
265 sub = col.column(align=True)
266 sub.operator("gpencil.brush_add", icon='ZOOMIN', text="")
267 sub.operator("gpencil.brush_remove", icon='ZOOMOUT', text="")
268 sub.menu("GPENCIL_MT_brush_specials", icon='DOWNARROW_HLT', text="")
269 brush = context.active_gpencil_brush
271 if len(ts.gpencil_brushes) > 1:
273 sub = col.column(align=True)
274 sub.operator("gpencil.brush_move", icon='TRIA_UP', text="").type = 'UP'
275 sub.operator("gpencil.brush_move", icon='TRIA_DOWN', text="").type = 'DOWN'
278 if brush is not None:
280 row.prop(brush, "line_width")
281 row = layout.row(align=True)
282 row.prop(brush, "use_random_pressure", text='', icon='RNDCURVE')
283 row.prop(brush, "pen_sensitivity_factor", slider=True)
284 row.prop(brush, "use_pressure", text='', icon='STYLUS_PRESSURE')
285 row = layout.row(align=True)
286 row.prop(brush, "use_random_strength", text='', icon='RNDCURVE')
287 row.prop(brush, "strength", slider=True)
288 row.prop(brush, "use_strength_pressure", text='', icon='STYLUS_PRESSURE')
289 row = layout.row(align=True)
290 row.prop(brush, "random_press", slider=True)
292 row = layout.row(align=True)
293 row.prop(brush, "jitter", slider=True)
294 row.prop(brush, "use_jitter_pressure", text='', icon='STYLUS_PRESSURE')
296 row.prop(brush, "angle", slider=True)
297 row.prop(brush, "angle_factor", text="Factor", slider=True)
300 col = box.column(align=True)
301 col.label(text="Stroke Quality:")
302 col.prop(brush, "pen_smooth_factor")
303 col.prop(brush, "pen_smooth_steps")
305 row = col.row(align=False)
306 row.prop(brush, "pen_subdivision_steps")
307 row.prop(brush, "random_subdiv", text='Randomness', slider=True)
310 class GreasePencilStrokeSculptPanel:
312 # bl_space_type = 'IMAGE_EDITOR'
313 bl_label = "Sculpt Strokes"
314 bl_category = "Grease Pencil"
315 bl_region_type = 'TOOLS'
318 def poll(cls, context):
319 if context.gpencil_data is None:
322 gpd = context.gpencil_data
323 return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
326 def draw(self, context):
329 settings = context.tool_settings.gpencil_sculpt
331 brush = settings.brush
333 layout.column().prop(settings, "tool")
335 col = layout.column()
336 col.prop(brush, "size", slider=True)
337 row = col.row(align=True)
338 row.prop(brush, "strength", slider=True)
339 row.prop(brush, "use_pressure_strength", text="")
340 col.prop(brush, "use_falloff")
341 if tool in {'SMOOTH', 'RANDOMIZE'}:
342 row = layout.row(align=True)
343 row.prop(settings, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
344 row.prop(settings, "affect_strength", text="Strength", icon='COLOR', toggle=True)
345 row.prop(settings, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
349 if tool == 'THICKNESS':
350 layout.row().prop(brush, "direction", expand=True)
351 elif tool == 'PINCH':
352 row = layout.row(align=True)
353 row.prop_enum(brush, "direction", 'ADD', text="Pinch")
354 row.prop_enum(brush, "direction", 'SUBTRACT', text="Inflate")
355 elif settings.tool == 'TWIST':
356 row = layout.row(align=True)
357 row.prop_enum(brush, "direction", 'SUBTRACT', text="CW")
358 row.prop_enum(brush, "direction", 'ADD', text="CCW")
360 row = layout.row(align=True)
361 row.prop(settings, "use_select_mask")
362 row = layout.row(align=True)
363 row.prop(settings, "selection_alpha", slider=True)
366 layout.prop(brush, "affect_pressure")
369 class GreasePencilBrushCurvesPanel:
371 # bl_space_type = 'IMAGE_EDITOR'
372 bl_label = "Brush Curves"
373 bl_category = "Grease Pencil"
374 bl_region_type = 'TOOLS'
375 bl_options = {'DEFAULT_CLOSED'}
378 def poll(cls, context):
379 if context.active_gpencil_brush is None:
382 brush = context.active_gpencil_brush
386 def draw(self, context):
388 brush = context.active_gpencil_brush
390 layout.label("Sensitivity")
392 box.template_curve_mapping(brush, "curve_sensitivity", brush=True)
394 layout.label("Strength")
396 box.template_curve_mapping(brush, "curve_strength", brush=True)
398 layout.label("Jitter")
400 box.template_curve_mapping(brush, "curve_jitter", brush=True)
403 ###############################
405 class GPENCIL_PIE_tool_palette(Menu):
406 """A pie menu for quick access to Grease Pencil tools"""
407 bl_label = "Grease Pencil Tools"
409 def draw(self, context):
412 pie = layout.menu_pie()
413 gpd = context.gpencil_data
417 col.operator("gpencil.draw", text="Draw", icon='GREASEPENCIL').mode = 'DRAW'
418 col.operator("gpencil.draw", text="Straight Lines", icon='LINE_DATA').mode = 'DRAW_STRAIGHT'
419 col.operator("gpencil.draw", text="Poly", icon='MESH_DATA').mode = 'DRAW_POLY'
422 # XXX: needs a dedicated icon...
424 col.operator("gpencil.draw", text="Eraser", icon='FORCE_CURVE').mode = 'ERASER'
426 # E - "Settings" Palette is included here too, since it needs to be in a stable position...
427 if gpd and gpd.layers.active:
429 col.operator("wm.call_menu_pie", text="Settings...", icon='SCRIPTWIN').name = "GPENCIL_PIE_settings_palette"
433 if gpd.use_stroke_edit_mode and context.editable_gpencil_strokes:
435 pie.operator("gpencil.editmode_toggle", text="Exit Edit Mode", icon='EDIT')
439 row = col.row(align=True)
440 row.operator("transform.translate", icon='MAN_TRANS')
441 row.operator("transform.rotate", icon='MAN_ROT')
442 row.operator("transform.resize", text="Scale", icon='MAN_SCALE')
443 row = col.row(align=True)
444 row.label("Proportional Edit:")
445 row.prop(context.tool_settings, "proportional_edit", text="", icon_only=True)
446 row.prop(context.tool_settings, "proportional_edit_falloff", text="", icon_only=True)
448 # NW - Select (Non-Modal)
450 col.operator("gpencil.select_all", text="Select All", icon='PARTICLE_POINT')
451 col.operator("gpencil.select_all", text="Select Inverse", icon='BLANK1')
452 col.operator("gpencil.select_linked", text="Select Linked", icon='LINKED')
453 col.operator("gpencil.palettecolor_select", text="Select Color", icon='COLOR')
455 # NE - Select (Modal)
457 col.operator("gpencil.select_border", text="Border Select", icon='BORDER_RECT')
458 col.operator("gpencil.select_circle", text="Circle Select", icon='META_EMPTY')
459 col.operator("gpencil.select_lasso", text="Lasso Select", icon='BORDER_LASSO')
463 col.operator("gpencil.duplicate_move", icon='PARTICLE_PATH', text="Duplicate")
464 col.operator("gpencil.delete", icon='X', text="Delete...")
467 pie.operator("wm.call_menu_pie", text="More...").name = "GPENCIL_PIE_tools_more"
470 pie.operator("gpencil.editmode_toggle", text="Enable Stroke Editing", icon='EDIT')
473 class GPENCIL_PIE_settings_palette(Menu):
474 """A pie menu for quick access to Grease Pencil settings"""
475 bl_label = "Grease Pencil Settings"
478 def poll(cls, context):
479 return bool(context.gpencil_data and context.active_gpencil_layer)
481 def draw(self, context):
484 pie = layout.menu_pie()
485 # gpd = context.gpencil_data
486 gpl = context.active_gpencil_layer
487 palcolor = context.active_gpencil_palettecolor
488 brush = context.active_gpencil_brush
490 # W - Stroke draw settings
491 col = pie.column(align=True)
492 if palcolor is not None:
493 col.label(text="Stroke")
494 col.prop(palcolor, "color", text="")
495 col.prop(palcolor, "alpha", text="", slider=True)
497 # E - Fill draw settings
498 col = pie.column(align=True)
499 if palcolor is not None:
500 col.label(text="Fill")
501 col.prop(palcolor, "fill_color", text="")
502 col.prop(palcolor, "fill_alpha", text="", slider=True)
505 gpencil_active_brush_settings_simple(context, pie)
509 col.label("Active Layer: ")
512 row.operator_context = 'EXEC_REGION_WIN'
513 row.operator_menu_enum("gpencil.layer_change", "layer", text="", icon='GREASEPENCIL')
514 row.prop(gpl, "info", text="")
515 row.operator("gpencil.layer_remove", text="", icon='X')
518 row.prop(gpl, "lock")
519 row.prop(gpl, "hide")
520 col.prop(gpl, "use_onion_skinning")
522 # NW - Move stroke Down
523 col = pie.column(align=True)
524 col.label("Arrange Strokes")
525 col.operator("gpencil.stroke_arrange", text="Send to Back").direction = 'BOTTOM'
526 col.operator("gpencil.stroke_arrange", text="Send Backward").direction = 'DOWN'
528 # NE - Move stroke Up
529 col = pie.column(align=True)
530 col.label("Arrange Strokes")
531 col.operator("gpencil.stroke_arrange", text="Bring to Front").direction = 'TOP'
532 col.operator("gpencil.stroke_arrange", text="Bring Forward").direction = 'UP'
534 # SW - Move stroke to color
535 col = pie.column(align=True)
536 col.operator("gpencil.stroke_change_color", text="Move to Color")
539 col = pie.column(align=True)
540 col.label("Join Strokes")
542 row.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
543 row.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
544 col.operator("gpencil.stroke_flip", text="Flip direction")
546 gpd = context.gpencil_data
548 col.prop(gpd, "show_stroke_direction", text="Show drawing direction")
551 class GPENCIL_PIE_tools_more(Menu):
552 """A pie menu for accessing more Grease Pencil tools"""
553 bl_label = "More Grease Pencil Tools"
556 def poll(cls, context):
557 gpd = context.gpencil_data
558 return bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
560 def draw(self, context):
563 pie = layout.menu_pie()
564 # gpd = context.gpencil_data
566 col = pie.column(align=True)
567 col.operator("gpencil.copy", icon='COPYDOWN', text="Copy")
568 col.operator("gpencil.paste", icon='PASTEDOWN', text="Paste")
570 col = pie.column(align=True)
571 col.operator("gpencil.select_more", icon='ZOOMIN')
572 col.operator("gpencil.select_less", icon='ZOOMOUT')
574 pie.operator("transform.mirror", icon='MOD_MIRROR')
575 pie.operator("transform.bend", icon='MOD_SIMPLEDEFORM')
576 pie.operator("transform.shear", icon='MOD_TRIANGULATE')
577 pie.operator("transform.tosphere", icon='MOD_MULTIRES')
579 pie.operator("gpencil.convert", icon='OUTLINER_OB_CURVE', text="Convert...")
580 pie.operator("wm.call_menu_pie", text="Back to Main Palette...").name = "GPENCIL_PIE_tool_palette"
583 class GPENCIL_PIE_sculpt(Menu):
584 """A pie menu for accessing Grease Pencil stroke sculpting settings"""
585 bl_label = "Grease Pencil Sculpt"
588 def poll(cls, context):
589 gpd = context.gpencil_data
590 return bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
592 def draw(self, context):
595 pie = layout.menu_pie()
597 settings = context.tool_settings.gpencil_sculpt
598 brush = settings.brush
600 # W - Launch Sculpt Mode
603 col.prop(settings, "tool", text="")
604 col.operator("gpencil.brush_paint", text="Sculpt", icon='SCULPTMODE_HLT')
606 # E - Common Settings
607 col = pie.column(align=True)
608 col.prop(brush, "size", slider=True)
609 row = col.row(align=True)
610 row.prop(brush, "strength", slider=True)
611 # row.prop(brush, "use_pressure_strength", text="", icon_only=True)
612 col.prop(brush, "use_falloff")
613 if settings.tool in {'SMOOTH', 'RANDOMIZE'}:
614 row = col.row(align=True)
615 row.prop(settings, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
616 row.prop(settings, "affect_strength", text="Strength", icon='COLOR', toggle=True)
617 row.prop(settings, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
619 # S - Change Brush Type Shortcuts
621 row.prop_enum(settings, "tool", value='GRAB')
622 row.prop_enum(settings, "tool", value='PUSH')
623 row.prop_enum(settings, "tool", value='CLONE')
625 # N - Change Brush Type Shortcuts
627 row.prop_enum(settings, "tool", value='SMOOTH')
628 row.prop_enum(settings, "tool", value='THICKNESS')
629 row.prop_enum(settings, "tool", value='STRENGTH')
630 row.prop_enum(settings, "tool", value='RANDOMIZE')
633 ###############################
636 class GPENCIL_MT_snap(Menu):
639 def draw(self, context):
642 layout.operator("gpencil.snap_to_grid", text="Selection to Grid")
643 layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor").use_offset = False
644 layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor (Offset)").use_offset = True
648 layout.operator("gpencil.snap_cursor_to_selected", text="Cursor to Selected")
649 layout.operator("view3d.snap_cursor_to_center", text="Cursor to Center")
650 layout.operator("view3d.snap_cursor_to_grid", text="Cursor to Grid")
653 ###############################
656 class GPENCIL_UL_brush(UIList):
657 def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
658 # assert(isinstance(item, bpy.types.GPencilBrush)
661 if self.layout_type in {'DEFAULT', 'COMPACT'}:
662 row = layout.row(align=True)
663 row.prop(brush, "name", text="", emboss=False, icon='BRUSH_DATA')
664 elif self.layout_type == 'GRID':
665 layout.alignment = 'CENTER'
666 layout.label(text="", icon_value=icon)
669 class GPENCIL_UL_palettecolor(UIList):
670 def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
671 # assert(isinstance(item, bpy.types.PaletteColor)
674 if self.layout_type in {'DEFAULT', 'COMPACT'}:
676 layout.active = False
678 split = layout.split(percentage=0.25)
679 row = split.row(align=True)
680 row.prop(palcolor, "color", text="", emboss=palcolor.is_stroke_visible)
681 row.prop(palcolor, "fill_color", text="", emboss=palcolor.is_fill_visible)
682 split.prop(palcolor, "name", text="", emboss=False)
684 row = layout.row(align=True)
685 row.prop(palcolor, "lock", text="", emboss=False)
686 row.prop(palcolor, "hide", text="", emboss=False)
687 if palcolor.ghost is True:
688 icon = 'GHOST_DISABLED'
690 icon = 'GHOST_ENABLED'
691 row.prop(palcolor, "ghost", text="", icon=icon, emboss=False)
693 elif self.layout_type == 'GRID':
694 layout.alignment = 'CENTER'
695 layout.label(text="", icon_value=icon)
698 class GPENCIL_UL_layer(UIList):
699 def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
700 # assert(isinstance(item, bpy.types.GPencilLayer)
703 if self.layout_type in {'DEFAULT', 'COMPACT'}:
705 layout.active = False
707 row = layout.row(align=True)
713 row.label(text="", icon=icon)
714 row.prop(gpl, "info", text="", emboss=False)
716 row = layout.row(align=True)
717 row.prop(gpl, "lock", text="", emboss=False)
718 row.prop(gpl, "hide", text="", emboss=False)
719 row.prop(gpl, "unlock_color", text="", emboss=False)
720 elif self.layout_type == 'GRID':
721 layout.alignment = 'CENTER'
722 layout.label(text="", icon_value=icon)
725 class GPENCIL_MT_layer_specials(Menu):
728 def draw(self, context):
731 layout.operator("gpencil.layer_duplicate", icon='COPY_ID') # XXX: needs a dedicated icon
735 layout.operator("gpencil.reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
736 layout.operator("gpencil.hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
740 layout.operator("gpencil.lock_all", icon='LOCKED', text="Lock All")
741 layout.operator("gpencil.unlock_all", icon='UNLOCKED', text="UnLock All")
745 layout.operator("gpencil.layer_merge", icon='NLA', text="Merge Down")
748 class GPENCIL_MT_brush_specials(Menu):
751 def draw(self, context):
753 layout.operator("gpencil.brush_copy", icon='PASTEDOWN', text="Copy current drawing brush")
754 layout.operator("gpencil.brush_presets_create", icon='HELP', text="Create a set of predefined brushes")
757 class GPENCIL_MT_palettecolor_specials(Menu):
760 def draw(self, context):
763 layout.operator("gpencil.palettecolor_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
764 layout.operator("gpencil.palettecolor_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
768 layout.operator("gpencil.palettecolor_lock_all", icon='LOCKED', text="Lock All")
769 layout.operator("gpencil.palettecolor_unlock_all", icon='UNLOCKED', text="UnLock All")
770 layout.operator("gpencil.palettecolor_copy", icon='PASTEDOWN', text="Copy Color")
774 layout.operator("gpencil.palettecolor_select", icon='COLOR', text="Select Strokes")
777 class GreasePencilDataPanel:
779 # bl_space_type = 'IMAGE_EDITOR'
780 bl_label = "Grease Pencil Layers"
781 bl_region_type = 'UI'
784 def draw_header(self, context):
785 self.layout.prop(context.space_data, "show_grease_pencil", text="")
788 def draw(self, context):
791 # owner of Grease Pencil data
792 gpd_owner = context.gpencil_data_owner
793 gpd = context.gpencil_data
796 if context.space_data.type == 'VIEW_3D':
797 layout.prop(context.tool_settings, "grease_pencil_source", expand=True)
798 elif context.space_data.type == 'CLIP_EDITOR':
799 layout.prop(context.space_data, "grease_pencil_source", expand=True)
801 # Grease Pencil data selector
802 layout.template_ID(gpd_owner, "grease_pencil", new="gpencil.data_add", unlink="gpencil.data_unlink")
804 # Grease Pencil data...
805 if (gpd is None) or (not gpd.layers):
806 layout.operator("gpencil.layer_add", text="New Layer")
808 self.draw_layers(context, layout, gpd)
810 def draw_layers(self, context, layout, gpd):
814 if len(gpd.layers) >= 2:
818 col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index", rows=layer_rows)
822 sub = col.column(align=True)
823 sub.operator("gpencil.layer_add", icon='ZOOMIN', text="")
824 sub.operator("gpencil.layer_remove", icon='ZOOMOUT', text="")
826 gpl = context.active_gpencil_layer
828 sub.menu("GPENCIL_MT_layer_specials", icon='DOWNARROW_HLT', text="")
830 if len(gpd.layers) > 1:
833 sub = col.column(align=True)
834 sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
835 sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
839 sub = col.column(align=True)
840 sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
841 sub.operator("gpencil.layer_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
844 self.draw_layer(context, layout, gpl)
846 def draw_layer(self, context, layout, gpl):
847 row = layout.row(align=True)
848 row.prop(gpl, "opacity", text="Opacity", slider=True)
851 split = layout.split(percentage=0.5)
852 split.active = not gpl.lock
853 split.prop(gpl, "show_x_ray")
854 split.prop(gpl, "show_points")
856 # Offsets + Parenting (where available)
857 if context.space_data.type == 'VIEW_3D':
858 split = layout.split(percentage=0.5)
860 split = layout.column() # parenting is not available in 2D editors...
861 split.active = not gpl.lock
863 # Offsets - Color Tint
865 subcol = col.column(align=True)
867 subcol.prop(gpl, "tint_color", text="")
868 subcol.prop(gpl, "tint_factor", text="Factor", slider=True)
870 # Offsets - Thickness
871 row = col.row(align=True)
872 row.prop(gpl, "line_change", text="Thickness Change", slider=True)
873 row.operator("gpencil.stroke_apply_thickness", icon='STYLUS_PRESSURE', text="")
876 if context.space_data.type == 'VIEW_3D':
877 col = split.column(align=True)
878 col.label(text="Parent:")
879 col.prop(gpl, "parent", text="")
882 sub.prop(gpl, "parent_type", text="")
884 if parent and gpl.parent_type == 'BONE' and parent.type == 'ARMATURE':
885 sub.prop_search(gpl, "parent_bone", parent.data, "bones", text="")
889 # Full-Row - Frame Locking (and Delete Frame)
890 row = layout.row(align=True)
891 row.active = not gpl.lock
894 lock_status = iface_("Locked") if gpl.lock_frame else iface_("Unlocked")
895 lock_label = iface_("Frame: %d (%s)") % (gpl.active_frame.frame_number, lock_status)
897 lock_label = iface_("Lock Frame")
898 row.prop(gpl, "lock_frame", text=lock_label, icon='UNLOCKED')
899 row.operator("gpencil.active_frame_delete", text="", icon='X')
904 col = layout.column(align=True)
905 col.active = not gpl.lock
908 row.prop(gpl, "use_onion_skinning")
909 row.prop(gpl, "use_ghost_custom_colors", text="", icon='COLOR')
911 split = col.split(percentage=0.5)
912 split.active = gpl.use_onion_skinning
915 sub = split.column(align=True)
916 row = sub.row(align=True)
917 row.active = gpl.use_ghost_custom_colors
918 row.prop(gpl, "before_color", text="")
919 sub.prop(gpl, "ghost_before_range", text="Before")
922 sub = split.column(align=True)
923 row = sub.row(align=True)
924 row.active = gpl.use_ghost_custom_colors
925 row.prop(gpl, "after_color", text="")
926 sub.prop(gpl, "ghost_after_range", text="After")
929 class GreasePencilPaletteColorPanel:
931 bl_label = "Grease Pencil Colors"
932 bl_region_type = 'UI'
935 def poll(cls, context):
936 if context.gpencil_data is None:
939 gpd = context.gpencil_data
940 return bool(gpd.layers.active)
943 def draw(self, context):
945 palette = context.active_gpencil_palette
948 row = layout.row(align=True)
949 row.operator_context = 'EXEC_REGION_WIN'
950 row.operator_menu_enum("gpencil.palette_change", "palette", text="", icon='COLOR')
951 row.prop(palette, "name", text="")
952 row.operator("gpencil.palette_add", icon='ZOOMIN', text="")
953 row.operator("gpencil.palette_remove", icon='X', text="")
958 if len(palette.colors) >= 2:
962 col.template_list("GPENCIL_UL_palettecolor", "", palette, "colors", palette.colors, "active_index",
967 sub = col.column(align=True)
968 sub.operator("gpencil.palettecolor_add", icon='ZOOMIN', text="")
969 sub.operator("gpencil.palettecolor_remove", icon='ZOOMOUT', text="")
971 palcol = context.active_gpencil_palettecolor
973 sub.menu("GPENCIL_MT_palettecolor_specials", icon='DOWNARROW_HLT', text="")
975 if len(palette.colors) > 1:
978 sub = col.column(align=True)
979 sub.operator("gpencil.palettecolor_move", icon='TRIA_UP', text="").direction = 'UP'
980 sub.operator("gpencil.palettecolor_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
983 sub = row.row(align=True)
984 sub.label(text="Isolate:") # based on active color only
985 sub.operator("gpencil.palettecolor_isolate", icon='LOCKED', text="").affect_visibility = False
986 sub.operator("gpencil.palettecolor_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
987 sub = row.row(align=True)
988 sub.label(text="Lock:") # based on other stuff...
989 sub.operator("gpencil.stroke_lock_color", icon='BORDER_RECT', text="")
990 sub.operator("gpencil.palette_lock_layer", icon='COLOR', text="")
992 pcolor = palette.colors.active
994 self.draw_palettecolors(layout, pcolor)
996 # Draw palette colors
997 def draw_palettecolors(self, layout, pcolor):
999 split = layout.split(percentage=0.5)
1000 split.active = not pcolor.lock
1003 col = split.column(align=True)
1004 col.active = not pcolor.lock
1005 col.label(text="Stroke:")
1006 col.prop(pcolor, "color", text="")
1007 col.prop(pcolor, "alpha", slider=True)
1010 col = split.column(align=True)
1011 col.active = not pcolor.lock
1012 col.label(text="Fill:")
1013 col.prop(pcolor, "fill_color", text="")
1014 col.prop(pcolor, "fill_alpha", text="Opacity", slider=True)
1017 split = layout.split(percentage=0.5)
1018 split.active = not pcolor.lock
1020 col = split.column(align=True)
1021 col.active = not pcolor.lock
1022 col.prop(pcolor, "use_volumetric_strokes")
1023 col = split.column(align=True)
1024 col.active = not pcolor.lock
1025 col.prop(pcolor, "use_hq_fill")
1028 class GreasePencilToolsPanel:
1029 # For use in "2D" Editors without their own toolbar
1031 # bl_space_type = 'IMAGE_EDITOR'
1032 # bl_options = {'DEFAULT_CLOSED'}
1033 bl_label = "Grease Pencil Settings"
1034 bl_region_type = 'UI'
1037 def poll(cls, context):
1038 return (context.gpencil_data is not None)
1041 def draw(self, context):
1042 layout = self.layout
1044 # gpd_owner = context.gpencil_data_owner
1045 gpd = context.gpencil_data
1047 layout.prop(gpd, "use_stroke_edit_mode", text="Enable Editing", icon='EDIT', toggle=True)
1051 layout.label("Proportional Edit:")
1053 row.prop(context.tool_settings, "proportional_edit", text="")
1054 row.prop(context.tool_settings, "proportional_edit_falloff", text="")
1059 gpencil_active_brush_settings_simple(context, layout)
1063 gpencil_stroke_placement_settings(context, layout)