# ##### BEGIN GPL LICENSE BLOCK ##### # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # ##### END GPL LICENSE BLOCK ##### # import bpy from bpy.types import Menu, UIList from bpy.app.translations import pgettext_iface as iface_ def gpencil_stroke_placement_settings(context, layout): if context.space_data.type == 'VIEW_3D': propname = "annotation_stroke_placement_view3d" elif context.space_data.type == 'SEQUENCE_EDITOR': propname = "annotation_stroke_placement_sequencer_preview" elif context.space_data.type == 'IMAGE_EDITOR': propname = "annotation_stroke_placement_image_editor" else: propname = "annotation_stroke_placement_view2d" tool_settings = context.tool_settings col = layout.column(align=True) if context.space_data.type != 'VIEW_3D': col.label(text="Stroke Placement:") row = col.row(align=True) row.prop_enum(tool_settings, propname, 'VIEW') row.prop_enum(tool_settings, propname, 'CURSOR', text="Cursor") def gpencil_active_brush_settings_simple(context, layout): tool_settings = context.tool_settings brush = tool_settings.gpencil_paint.brush if brush is None: layout.label(text="No Active Brush") return col = layout.column() col.label(text="Active Brush: ") row = col.row(align=True) row.operator_context = 'EXEC_REGION_WIN' row.operator_menu_enum("gpencil.brush_change", "brush", text="", icon='BRUSH_DATA') row.prop(brush, "name", text="") col.prop(brush, "size", slider=True) row = col.row(align=True) row.prop(brush, "use_random_pressure", text="", icon='RNDCURVE') row.prop(brush, "pen_sensitivity_factor", slider=True) row.prop(brush, "use_pressure", text="", icon='STYLUS_PRESSURE') row = col.row(align=True) row.prop(brush, "use_random_strength", text="", icon='RNDCURVE') row.prop(brush, "strength", slider=True) row.prop(brush, "use_strength_pressure", text="", icon='STYLUS_PRESSURE') row = col.row(align=True) row.prop(brush, "jitter", slider=True) row.prop(brush, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE') row = col.row() row.prop(brush, "angle", slider=True) row.prop(brush, "angle_factor", text="Factor", slider=True) # XXX: To be replaced with active tools class AnnotationDrawingToolsPanel: # subclass must set # bl_space_type = 'IMAGE_EDITOR' bl_label = "Annotation" bl_category = "Annotation" bl_region_type = 'TOOLS' def draw(self, context): layout = self.layout is_3d_view = context.space_data.type == 'VIEW_3D' is_clip_editor = context.space_data.type == 'CLIP_EDITOR' col = layout.column(align=True) col.label(text="Draw:") row = col.row(align=True) row.operator("gpencil.annotate", icon='GREASEPENCIL', text="Draw").mode = 'DRAW' # XXX: Needs a dedicated icon row.operator("gpencil.annotate", icon='FORCE_CURVE', text="Erase").mode = 'ERASER' row = col.row(align=True) row.operator("gpencil.annotate", icon='LINE_DATA', text="Line").mode = 'DRAW_STRAIGHT' row.operator("gpencil.annotate", icon='MESH_DATA', text="Poly").mode = 'DRAW_POLY' col.separator() sub = col.column(align=True) sub.operator("gpencil.blank_frame_add", icon='FILE_NEW') sub.operator("gpencil.active_frames_delete_all", icon='X', text="Delete Frame(s)") #sub = col.column(align=True) #sub.prop(context.tool_settings, "use_gpencil_draw_additive", text="Additive Drawing") #sub.prop(context.tool_settings, "use_gpencil_continuous_drawing", text="Continuous Drawing") #sub.prop(context.tool_settings, "use_gpencil_draw_onback", text="Draw on Back") col.separator() col.separator() if context.space_data.type == 'CLIP_EDITOR': col.separator() col.label(text="Data Source:") row = col.row(align=True) if is_3d_view: row.prop(context.tool_settings, "grease_pencil_source", expand=True) elif is_clip_editor: row.prop(context.space_data, "grease_pencil_source", expand=True) # col.separator() # col.separator() gpencil_stroke_placement_settings(context, col) class GreasePencilSculptOptionsPanel: bl_label = "Sculpt Strokes" @classmethod def poll(cls, context): settings = context.tool_settings.gpencil_sculpt tool = settings.sculpt_tool return bool(tool in {'SMOOTH', 'RANDOMIZE', 'SMOOTH'}) def draw(self, context): layout = self.layout layout.use_property_split = True layout.use_property_decorate = False settings = context.tool_settings.gpencil_sculpt tool = settings.sculpt_tool brush = settings.brush if tool in {'SMOOTH', 'RANDOMIZE'}: layout.prop(settings, "use_edit_position", text="Affect Position") layout.prop(settings, "use_edit_strength", text="Affect Strength") layout.prop(settings, "use_edit_thickness", text="Affect Thickness") if tool == 'SMOOTH': layout.prop(brush, "use_edit_pressure") layout.prop(settings, "use_edit_uv", text="Affect UV") # GP Object Tool Settings class GreasePencilDisplayPanel: bl_label = "Brush Tip" bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): ob = context.active_object brush = context.tool_settings.gpencil_paint.brush if ob and ob.type == 'GPENCIL' and brush: if context.mode == 'PAINT_GPENCIL': return brush.gpencil_tool != 'ERASE' else: # GP Sculpt and Weight Paint always have Brush Tip panel. return True def draw_header(self, context): if self.is_popover: return if context.mode == 'PAINT_GPENCIL': brush = context.tool_settings.gpencil_paint.brush gp_settings = brush.gpencil_settings self.layout.prop(gp_settings, "use_cursor", text="") elif context.mode in {'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}: settings = context.tool_settings.gpencil_sculpt brush = settings.brush self.layout.prop(brush, "use_cursor", text="") def draw(self, context): layout = self.layout layout.use_property_split = True layout.use_property_decorate = False tool_settings = context.tool_settings ob = context.active_object if ob.mode == 'PAINT_GPENCIL': brush = tool_settings.gpencil_paint.brush gp_settings = brush.gpencil_settings if self.is_popover: row = layout.row(align=True) row.prop(gp_settings, "use_cursor", text="") row.label(text="Display Cursor") col = layout.column(align=True) col.active = gp_settings.use_cursor if brush.gpencil_tool == 'DRAW': col.prop(gp_settings, "show_lasso", text="Show Fill Color While Drawing") if brush.gpencil_tool == 'FILL': col.prop(brush, "cursor_color_add", text="Cursor Color") elif ob.mode in {'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}: settings = tool_settings.gpencil_sculpt brush = settings.brush tool = settings.sculpt_tool if self.is_popover: row = layout.row(align=True) row.prop(brush, "use_cursor", text="") row.label(text="Display Cursor") col = layout.column(align=True) col.active = brush.use_cursor if tool in {'THICKNESS', 'STRENGTH'}: col.prop(brush, "cursor_color_add", text="Add Cursor Color") col.prop(brush, "cursor_color_sub", text="Subtract Cursor Color") elif tool == 'PINCH': col.prop(brush, "cursor_color_add", text="Pinch Cursor Color") col.prop(brush, "cursor_color_sub", text="Inflate Cursor Color") elif tool == 'TWIST': col.prop(brush, "cursor_color_add", text="CCW Cursor Color") col.prop(brush, "cursor_color_sub", text="CW Cursor Color") else: col.prop(brush, "cursor_color_add", text="Cursor Color") class GPENCIL_MT_pie_tool_palette(Menu): """A pie menu for quick access to Grease Pencil tools""" bl_label = "Grease Pencil Tools" def draw(self, context): layout = self.layout pie = layout.menu_pie() gpd = context.gpencil_data # W - Drawing Types col = pie.column() col.operator("gpencil.draw", text="Draw", icon='GREASEPENCIL').mode = 'DRAW' col.operator("gpencil.draw", text="Straight Lines", icon='LINE_DATA').mode = 'DRAW_STRAIGHT' col.operator("gpencil.draw", text="Poly", icon='MESH_DATA').mode = 'DRAW_POLY' # E - Eraser # XXX: needs a dedicated icon... col = pie.column() col.operator("gpencil.draw", text="Eraser", icon='FORCE_CURVE').mode = 'ERASER' # E - "Settings" Palette is included here too, since it needs to be in a stable position... if gpd and gpd.layers.active: col.separator() col.operator( "wm.call_menu_pie", text="Settings...", icon='SCRIPTWIN').name = "GPENCIL_MT_pie_settings_palette" # Editing tools if gpd: if gpd.use_stroke_edit_mode and context.editable_gpencil_strokes: # S - Exit Edit Mode pie.operator("gpencil.editmode_toggle", text="Exit Edit Mode", icon='EDIT') # N - Transforms col = pie.column() row = col.row(align=True) row.operator("transform.translate", icon='MAN_TRANS') row.operator("transform.rotate", icon='MAN_ROT') row.operator("transform.resize", text="Scale", icon='MAN_SCALE') row = col.row(align=True) row.label(text="Proportional Edit:") row.prop(context.tool_settings, "use_proportional_edit", text="", icon_only=True) row.prop(context.tool_settings, "proportional_edit_falloff", text="", icon_only=True) # NW - Select (Non-Modal) col = pie.column() col.operator("gpencil.select_all", text="Select All", icon='PARTICLE_POINT') col.operator("gpencil.select_all", text="Select Inverse", icon='BLANK1') col.operator("gpencil.select_linked", text="Select Linked", icon='LINKED') col.operator("gpencil.palettecolor_select", text="Select Color", icon='COLOR') # NE - Select (Modal) col = pie.column() col.operator("gpencil.select_box", text="Box Select", icon='BORDER_RECT') col.operator("gpencil.select_circle", text="Circle Select", icon='META_EMPTY') col.operator("gpencil.select_lasso", text="Lasso Select", icon='BORDER_LASSO') col.operator("gpencil.select_alternate", text="Alternate Select", icon='BORDER_LASSO') # SW - Edit Tools col = pie.column() col.operator("gpencil.duplicate_move", icon='PARTICLE_PATH', text="Duplicate") col.operator("gpencil.delete", icon='X', text="Delete...") # SE - More Tools pie.operator("wm.call_menu_pie", text="More...").name = "GPENCIL_MT_pie_tools_more" else: # Toggle Edit Mode pie.operator("gpencil.editmode_toggle", text="Enable Stroke Editing", icon='EDIT') class GPENCIL_MT_pie_settings_palette(Menu): """A pie menu for quick access to Grease Pencil settings""" bl_label = "Grease Pencil Settings" @classmethod def poll(cls, context): return bool(context.gpencil_data and context.active_gpencil_layer) def draw(self, context): layout = self.layout pie = layout.menu_pie() gpd = context.gpencil_data gpl = context.active_gpencil_layer palcolor = None # context.active_gpencil_palettecolor is_editmode = bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes) # W - Stroke draw settings col = pie.column(align=True) if palcolor is not None: col.enabled = not palcolor.lock col.label(text="Stroke") col.prop(palcolor, "color", text="") col.prop(palcolor, "alpha", text="", slider=True) # E - Fill draw settings col = pie.column(align=True) if palcolor is not None: col.enabled = not palcolor.lock col.label(text="Fill") col.prop(palcolor, "fill_color", text="") col.prop(palcolor, "fill_alpha", text="", slider=True) # S Brush settings gpencil_active_brush_settings_simple(context, pie) # N - Active Layer col = pie.column() col.label(text="Active Layer: ") row = col.row() row.operator_context = 'EXEC_REGION_WIN' row.operator_menu_enum("gpencil.layer_change", "layer", text="", icon='GREASEPENCIL') row.prop(gpl, "info", text="") row.operator("gpencil.layer_remove", text="", icon='X') row = col.row() row.prop(gpl, "lock") row.prop(gpl, "hide") col.prop(gpl, "use_onion_skinning") # NW/NE/SW/SE - These operators are only available in editmode # as they require strokes to be selected to work if is_editmode: # NW - Move stroke Down col = pie.column(align=True) col.label(text="Arrange Strokes") col.operator("gpencil.stroke_arrange", text="Send to Back").direction = 'BOTTOM' col.operator("gpencil.stroke_arrange", text="Send Backward").direction = 'DOWN' # NE - Move stroke Up col = pie.column(align=True) col.label(text="Arrange Strokes") col.operator("gpencil.stroke_arrange", text="Bring to Front").direction = 'TOP' col.operator("gpencil.stroke_arrange", text="Bring Forward").direction = 'UP' # SW - Move stroke to color col = pie.column(align=True) col.operator("gpencil.stroke_change_color", text="Move to Color") # SE - Join strokes col = pie.column(align=True) col.label(text="Join Strokes") row = col.row() row.operator("gpencil.stroke_join", text="Join").type = 'JOIN' row.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY' col.operator("gpencil.stroke_flip", text="Flip Direction") col.prop(gpd, "show_stroke_direction", text="Show Drawing Direction") class GPENCIL_MT_pie_tools_more(Menu): """A pie menu for accessing more Grease Pencil tools""" bl_label = "More Grease Pencil Tools" @classmethod def poll(cls, context): gpd = context.gpencil_data return bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes) def draw(self, _context): layout = self.layout pie = layout.menu_pie() # gpd = context.gpencil_data col = pie.column(align=True) col.operator("gpencil.copy", text="Copy", icon='COPYDOWN') col.operator("gpencil.paste", text="Paste", icon='PASTEDOWN').type = 'ACTIVE' col.operator("gpencil.paste", text="Paste by Layer").type = 'LAYER' col = pie.column(align=True) col.operator("gpencil.select_more", icon='ADD') col.operator("gpencil.select_less", icon='REMOVE') pie.operator("transform.mirror", icon='MOD_MIRROR') pie.operator("transform.bend", icon='MOD_SIMPLEDEFORM') pie.operator("transform.shear", icon='MOD_TRIANGULATE') pie.operator("transform.tosphere", icon='MOD_MULTIRES') pie.operator("gpencil.convert", icon='OUTLINER_OB_CURVE', text="Convert...") pie.operator("wm.call_menu_pie", text="Back to Main Palette...").name = "GPENCIL_MT_pie_tool_palette" class GPENCIL_MT_pie_sculpt(Menu): """A pie menu for accessing Grease Pencil stroke sculpt settings""" bl_label = "Grease Pencil Sculpt" @classmethod def poll(cls, context): gpd = context.gpencil_data return bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes) def draw(self, context): layout = self.layout pie = layout.menu_pie() settings = context.tool_settings.gpencil_sculpt brush = settings.brush # W - Launch Sculpt Mode col = pie.column() # col.label(text="Tool:") col.prop(settings, "sculpt_tool", text="") col.operator("gpencil.sculpt_paint", text="Sculpt", icon='SCULPTMODE_HLT') # E - Common Settings col = pie.column(align=True) col.prop(brush, "size", slider=True) row = col.row(align=True) row.prop(brush, "strength", slider=True) # row.prop(brush, "use_pressure_strength", text="", icon_only=True) col.prop(brush, "use_falloff") if settings.sculpt_tool in {'SMOOTH', 'RANDOMIZE'}: row = col.row(align=True) row.prop(settings, "use_edit_position", text="Position", icon='MESH_DATA', toggle=True) row.prop(settings, "use_edit_strength", text="Strength", icon='COLOR', toggle=True) row.prop(settings, "use_edit_thickness", text="Thickness", icon='LINE_DATA', toggle=True) # S - Change Brush Type Shortcuts row = pie.row() row.prop_enum(settings, "tool", value='GRAB') row.prop_enum(settings, "tool", value='PUSH') row.prop_enum(settings, "tool", value='CLONE') # N - Change Brush Type Shortcuts row = pie.row() row.prop_enum(settings, "tool", value='SMOOTH') row.prop_enum(settings, "tool", value='THICKNESS') row.prop_enum(settings, "tool", value='STRENGTH') row.prop_enum(settings, "tool", value='RANDOMIZE') class GPENCIL_MT_snap(Menu): bl_label = "Snap" def draw(self, _context): layout = self.layout layout.operator("gpencil.snap_to_grid", text="Selection to Grid") layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor").use_offset = False layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor (Keep Offset)").use_offset = True layout.separator() layout.operator("gpencil.snap_cursor_to_selected", text="Cursor to Selected") layout.operator("view3d.snap_cursor_to_center", text="Cursor to World Origin") layout.operator("view3d.snap_cursor_to_grid", text="Cursor to Grid") class GPENCIL_MT_move_to_layer(Menu): bl_label = "Move to Layer" def draw(self, context): layout = self.layout gpd = context.gpencil_data if gpd: gpl_active = context.active_gpencil_layer tot_layers = len(gpd.layers) i = tot_layers - 1 while(i >= 0): gpl = gpd.layers[i] if gpl.info == gpl_active.info: icon = 'GREASEPENCIL' else: icon = 'NONE' layout.operator("gpencil.move_to_layer", text=gpl.info, icon=icon).layer = i i -= 1 layout.separator() layout.operator("gpencil.layer_add", text="New Layer", icon='ADD') class GPENCIL_MT_gpencil_draw_delete(Menu): bl_label = "Delete" def draw(self, _context): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' layout.operator("gpencil.delete", text="Delete Active Keyframe (Active Layer)").type = 'FRAME' layout.operator("gpencil.active_frames_delete_all", text="Delete Active Keyframes (All Layers)") class GPENCIL_MT_cleanup(Menu): bl_label = "Clean Up" def draw(self, context): ob = context.active_object layout = self.layout layout.operator("gpencil.frame_clean_loose", text="Delete Loose Points") if ob.mode != 'PAINT_GPENCIL': layout.operator("gpencil.stroke_merge_by_distance", text="Merge by Distance") layout.separator() layout.operator("gpencil.frame_clean_fill", text="Boundary Strokes").mode = 'ACTIVE' layout.operator("gpencil.frame_clean_fill", text="Boundary Strokes all Frames").mode = 'ALL' if ob.mode != 'PAINT_GPENCIL': layout.separator() layout.operator("gpencil.reproject") class GPENCIL_UL_annotation_layer(UIList): def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index): # assert(isinstance(item, bpy.types.GPencilLayer) gpl = item if self.layout_type in {'DEFAULT', 'COMPACT'}: if gpl.lock: layout.active = False split = layout.split(factor=0.2) split.prop(gpl, "color", text="", emboss=True) split.prop(gpl, "info", text="", emboss=False) row = layout.row(align=True) row.prop(gpl, "annotation_hide", text="", emboss=False) elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) class AnnotationDataPanel: bl_label = "Annotations" bl_region_type = 'UI' bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): # Show this panel as long as someone that might own this exists # AND the owner isn't an object (e.g. GP Object) if context.gpencil_data_owner is None: return False elif type(context.gpencil_data_owner) is bpy.types.Object: return False else: return True def draw_header(self, context): if context.space_data.type not in {'VIEW_3D', 'TOPBAR'}: self.layout.prop(context.space_data, "show_annotation", text="") def draw(self, context): layout = self.layout layout.use_property_decorate = False # Grease Pencil owner. gpd_owner = context.gpencil_data_owner gpd = context.gpencil_data # Owner selector. if context.space_data.type == 'CLIP_EDITOR': layout.row().prop(context.space_data, "grease_pencil_source", expand=True) layout.template_ID(gpd_owner, "grease_pencil", new="gpencil.data_add", unlink="gpencil.data_unlink") # List of layers/notes. if gpd and gpd.layers: self.draw_layers(context, layout, gpd) def draw_layers(self, context, layout, gpd): row = layout.row() col = row.column() if len(gpd.layers) >= 2: layer_rows = 5 else: layer_rows = 3 col.template_list("GPENCIL_UL_annotation_layer", "", gpd, "layers", gpd.layers, "active_index", rows=layer_rows, sort_reverse=True, sort_lock=True) col = row.column() sub = col.column(align=True) sub.operator("gpencil.layer_add", icon='ADD', text="") sub.operator("gpencil.layer_remove", icon='REMOVE', text="") gpl = context.active_gpencil_layer if gpl: if len(gpd.layers) > 1: col.separator() sub = col.column(align=True) sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP' sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN' tool_settings = context.tool_settings if gpd and gpl: layout.prop(gpl, "thickness") else: layout.prop(tool_settings, "annotation_thickness", text="Thickness") if gpl: # Full-Row - Frame Locking (and Delete Frame) row = layout.row(align=True) row.active = not gpl.lock if gpl.active_frame: lock_status = iface_("Locked") if gpl.lock_frame else iface_("Unlocked") lock_label = iface_("Frame: %d (%s)") % (gpl.active_frame.frame_number, lock_status) else: lock_label = iface_("Lock Frame") row.prop(gpl, "lock_frame", text=lock_label, icon='UNLOCKED') row.operator("gpencil.active_frame_delete", text="", icon='X') class AnnotationOnionSkin: bl_label = "Onion Skin" bl_region_type = 'UI' bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): # Show this panel as long as someone that might own this exists # AND the owner isn't an object (e.g. GP Object) if context.gpencil_data_owner is None: return False elif type(context.gpencil_data_owner) is bpy.types.Object: return False else: gpl = context.active_gpencil_layer if gpl is None: return False return True def draw_header(self, context): gpl = context.active_gpencil_layer self.layout.prop(gpl, "use_annotation_onion_skinning", text="") def draw(self, context): layout = self.layout layout.use_property_decorate = False gpl = context.active_gpencil_layer col = layout.column() split = col.split(factor=0.5) split.active = gpl.use_annotation_onion_skinning # - Before Frames sub = split.column(align=True) row = sub.row(align=True) row.prop(gpl, "annotation_onion_before_color", text="") sub.prop(gpl, "annotation_onion_before_range", text="Before") # - After Frames sub = split.column(align=True) row = sub.row(align=True) row.prop(gpl, "annotation_onion_after_color", text="") sub.prop(gpl, "annotation_onion_after_range", text="After") class GreasePencilToolsPanel: # For use in "2D" Editors without their own toolbar # subclass must set # bl_space_type = 'IMAGE_EDITOR' bl_label = "Grease Pencil Settings" bl_region_type = 'UI' bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): # XXX - disabled in 2.8 branch. return False return (context.gpencil_data is not None) def draw(self, context): layout = self.layout gpencil_active_brush_settings_simple(context, layout) layout.separator() gpencil_stroke_placement_settings(context, layout) class GreasePencilMaterialsPanel: # Mix-in, use for properties editor and top-bar. def draw(self, context): layout = self.layout show_full_ui = (self.bl_space_type == 'PROPERTIES') is_view3d = (self.bl_space_type == 'VIEW_3D') tool_settings = context.scene.tool_settings gpencil_paint = tool_settings.gpencil_paint brush = gpencil_paint.brush ob = context.object row = layout.row() if ob: is_sortable = len(ob.material_slots) > 1 rows = 7 row.template_list("GPENCIL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows) # if topbar popover and brush pinned, disable if is_view3d and brush is not None: gp_settings = brush.gpencil_settings if gp_settings.use_material_pin: row.enabled = False col = row.column(align=True) if show_full_ui: col.operator("object.material_slot_add", icon='ADD', text="") col.operator("object.material_slot_remove", icon='REMOVE', text="") col.separator() col.menu("GPENCIL_MT_color_context_menu", icon='DOWNARROW_HLT', text="") if is_sortable: col.separator() col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP' col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN' col.separator() sub = col.column(align=True) sub.operator("gpencil.color_isolate", icon='RESTRICT_VIEW_ON', text="").affect_visibility = True sub.operator("gpencil.color_isolate", icon='LOCKED', text="").affect_visibility = False if show_full_ui: row = layout.row() row.template_ID(ob, "active_material", new="material.new", live_icon=True) slot = context.material_slot if slot: icon_link = 'MESH_DATA' if slot.link == 'DATA' else 'OBJECT_DATA' row.prop(slot, "link", icon=icon_link, icon_only=True) if ob.data.use_stroke_edit_mode: row = layout.row(align=True) row.operator("gpencil.stroke_change_color", text="Assign") row.operator("gpencil.color_select", text="Select").deselect = False row.operator("gpencil.color_select", text="Deselect").deselect = True # stroke color ma = None if is_view3d and brush is not None: gp_settings = brush.gpencil_settings if gp_settings.use_material_pin is False: if ob.active_material_index >= 0: ma = ob.material_slots[ob.active_material_index].material else: ma = gp_settings.material if ma is not None and ma.grease_pencil is not None: gpcolor = ma.grease_pencil if ( gpcolor.stroke_style == 'SOLID' or gpcolor.use_stroke_pattern or gpcolor.use_stroke_texture_mix ): row = layout.row() row.prop(gpcolor, "color", text="Stroke Color") else: space = context.space_data row.template_ID(space, "pin_id") class GPENCIL_UL_layer(UIList): def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index): # assert(isinstance(item, bpy.types.GPencilLayer) gpl = item if self.layout_type in {'DEFAULT', 'COMPACT'}: if gpl.lock: layout.active = False row = layout.row(align=True) row.label( text="", icon='BONE_DATA' if gpl.is_parented else 'BLANK1', ) row.prop(gpl, "info", text="", emboss=False) row = layout.row(align=True) row.prop(gpl, "mask_layer", text="", icon='MOD_MASK' if gpl.mask_layer else 'LAYER_ACTIVE', emboss=False) subrow = row.row(align=True) subrow.prop( gpl, "use_onion_skinning", text="", icon='ONIONSKIN_ON' if gpl.use_onion_skinning else 'ONIONSKIN_OFF', emboss=False, ) row.prop(gpl, "hide", text="", emboss=False) row.prop(gpl, "lock", text="", emboss=False) elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label( text="", icon_value=icon, ) class GreasePencilSimplifyPanel: def draw_header(self, context): rd = context.scene.render self.layout.prop(rd, "simplify_gpencil", text="") def draw(self, context): layout = self.layout layout.use_property_split = True layout.use_property_decorate = False rd = context.scene.render layout.active = rd.simplify_gpencil col = layout.column() col.prop(rd, "simplify_gpencil_onplay", text="Playback Only") col.prop(rd, "simplify_gpencil_view_modifier", text="Modifiers") col.prop(rd, "simplify_gpencil_shader_fx", text="ShaderFX") col.prop(rd, "simplify_gpencil_blend", text="Layers Blending") col.prop(rd, "simplify_gpencil_tint", text="Layers Tinting") col.prop(rd, "simplify_gpencil_view_fill") sub = col.column() sub.active = rd.simplify_gpencil_view_fill sub.prop(rd, "simplify_gpencil_remove_lines", text="Lines") class GreasePencilLayerAdjustmentsPanel: def draw(self, context): layout = self.layout layout.use_property_split = True scene = context.scene ob = context.object gpd = ob.data gpl = gpd.layers.active layout.active = not gpl.lock # Layer options # Offsets - Color Tint layout.enabled = not gpl.lock col = layout.column(align=True) col.prop(gpl, "tint_color") col.prop(gpl, "tint_factor", text="Factor", slider=True) # Offsets - Thickness col = layout.row(align=True) col.prop(gpl, "line_change", text="Stroke Thickness") col = layout.row(align=True) col.prop(gpl, "pass_index") col = layout.row(align=True) col.prop_search(gpl, "viewlayer_render", scene, "view_layers", text="View Layer") col = layout.row(align=True) col.prop(gpl, "lock_material") class GreasePencilLayerRelationsPanel: def draw(self, context): layout = self.layout layout.use_property_split = True layout.use_property_decorate = False ob = context.object gpd = ob.data gpl = gpd.layers.active col = layout.column() col.active = not gpl.lock col.prop(gpl, "parent") col.prop(gpl, "parent_type", text="Type") parent = gpl.parent if parent and gpl.parent_type == 'BONE' and parent.type == 'ARMATURE': col.prop_search(gpl, "parent_bone", parent.data, "bones", text="Bone") class GreasePencilLayerDisplayPanel: def draw(self, context): layout = self.layout layout.use_property_split = True layout.use_property_decorate = False ob = context.object gpd = ob.data gpl = gpd.layers.active col = layout.row(align=True) col.prop(gpl, "channel_color") col = layout.row(align=True) col.prop(gpl, "use_solo_mode", text="Show Only On Keyframed") classes = ( GPENCIL_MT_pie_tool_palette, GPENCIL_MT_pie_settings_palette, GPENCIL_MT_pie_tools_more, GPENCIL_MT_pie_sculpt, GPENCIL_MT_snap, GPENCIL_MT_cleanup, GPENCIL_MT_move_to_layer, GPENCIL_MT_gpencil_draw_delete, GPENCIL_UL_annotation_layer, GPENCIL_UL_layer, ) if __name__ == "__main__": # only for live edit. from bpy.utils import register_class for cls in classes: register_class(cls)