# SPDX-License-Identifier: GPL-2.0-or-later import bpy from bpy.types import Menu, UIList, Operator from bpy.app.translations import pgettext_iface as iface_ # XXX: To be replaced with active tools # Currently only used by the clip editor 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 tool_settings = context.tool_settings 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() col.label(text="Stroke Placement:") row = col.row(align=True) row.prop_enum(tool_settings, "annotation_stroke_placement_view2d", 'VIEW') row.prop_enum(tool_settings, "annotation_stroke_placement_view2d", 'IMAGE', text="Image") class GreasePencilSculptAdvancedPanel: def draw(self, context): layout = self.layout layout.use_property_split = True layout.use_property_decorate = False tool_settings = context.scene.tool_settings brush = tool_settings.gpencil_sculpt_paint.brush tool = brush.gpencil_sculpt_tool gp_settings = brush.gpencil_settings if tool in {'SMOOTH', 'RANDOMIZE'}: col = layout.column(heading="Affect", align=True) col.prop(gp_settings, "use_edit_position", text="Position") col.prop(gp_settings, "use_edit_strength", text="Strength") col.prop(gp_settings, "use_edit_thickness", text="Thickness") col.prop(gp_settings, "use_edit_uv", text="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, Vertex and Weight Paint always have Brush Tip panel. return True return False def draw_header(self, context): if self.is_popover: return tool_settings = context.tool_settings if context.mode == 'PAINT_GPENCIL': settings = tool_settings.gpencil_paint elif context.mode == 'SCULPT_GPENCIL': settings = tool_settings.gpencil_sculpt_paint elif context.mode == 'WEIGHT_GPENCIL': settings = tool_settings.gpencil_weight_paint elif context.mode == 'VERTEX_GPENCIL': settings = tool_settings.gpencil_vertex_paint brush = settings.brush if brush: self.layout.prop(settings, "show_brush", text="") def draw(self, context): layout = self.layout layout.use_property_split = True layout.use_property_decorate = False tool_settings = context.tool_settings if context.mode == 'PAINT_GPENCIL': settings = tool_settings.gpencil_paint elif context.mode == 'SCULPT_GPENCIL': settings = tool_settings.gpencil_sculpt_paint elif context.mode == 'WEIGHT_GPENCIL': settings = tool_settings.gpencil_weight_paint elif context.mode == 'VERTEX_GPENCIL': settings = tool_settings.gpencil_vertex_paint brush = settings.brush gp_settings = brush.gpencil_settings ob = context.active_object if ob.mode == 'PAINT_GPENCIL': if self.is_popover: row = layout.row(align=True) row.prop(settings, "show_brush", text="Display Cursor") col = layout.column(align=True) col.active = settings.show_brush if brush.gpencil_tool == 'DRAW': col.prop(gp_settings, "show_lasso", text="Show Fill Color While Drawing") elif ob.mode == 'SCULPT_GPENCIL': col = layout.column(align=True) col.active = settings.show_brush col.prop(brush, "cursor_color_add", text="Cursor Color") if brush.gpencil_sculpt_tool in {'THICKNESS', 'STRENGTH', 'PINCH', 'TWIST'}: col.prop(brush, "cursor_color_subtract", text="Inverse Color") elif ob.mode == 'WEIGHT_GPENCIL': col = layout.column(align=True) col.active = settings.show_brush col.prop(brush, "cursor_color_add", text="Cursor Color") elif ob.mode == 'VERTEX_GPENCIL': row = layout.row(align=True) row.prop(settings, "show_brush", text="") row.label(text="Display Cursor") class GreasePencilBrushFalloff: bl_label = "Falloff" bl_options = {'DEFAULT_CLOSED'} def draw(self, context): layout = self.layout ts = context.tool_settings settings = None if context.mode == 'PAINT_GPENCIL': settings = ts.gpencil_paint if context.mode == 'SCULPT_GPENCIL': settings = ts.gpencil_sculpt_paint elif context.mode == 'WEIGHT_GPENCIL': settings = ts.gpencil_weight_paint elif context.mode == 'VERTEX_GPENCIL': settings = ts.gpencil_vertex_paint if settings: brush = settings.brush col = layout.column(align=True) row = col.row(align=True) row.prop(brush, "curve_preset", text="") if brush.curve_preset == 'CUSTOM': layout.template_curve_mapping(brush, "curve", brush=True) col = layout.column(align=True) row = col.row(align=True) row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH' row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND' row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT' row.operator("brush.curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP' row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE' row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX' 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_snap_pie(Menu): bl_label = "Snap" def draw(self, _context): layout = self.layout pie = layout.menu_pie() pie.operator("view3d.snap_cursor_to_grid", text="Cursor to Grid", icon='CURSOR') pie.operator("gpencil.snap_to_grid", text="Selection to Grid", icon='RESTRICT_SELECT_OFF') pie.operator("gpencil.snap_cursor_to_selected", text="Cursor to Selected", icon='CURSOR') pie.operator( "gpencil.snap_to_cursor", text="Selection to Cursor", icon='RESTRICT_SELECT_OFF' ).use_offset = False pie.operator( "gpencil.snap_to_cursor", text="Selection to Cursor (Keep Offset)", icon='RESTRICT_SELECT_OFF' ).use_offset = True pie.separator() pie.operator("view3d.snap_cursor_to_center", text="Cursor to World Origin", icon='CURSOR') pie.separator() 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: layout.operator_context = 'INVOKE_REGION_WIN' layout.operator("gpencil.move_to_layer", text="New Layer", icon='ADD').layer = -1 layout.separator() 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, translate=False).layer = i i -= 1 class GPENCIL_MT_layer_active(Menu): bl_label = "Change Active Layer" def draw(self, context): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' gpd = context.gpencil_data if gpd: layout.operator("gpencil.layer_add", text="New Layer", icon='ADD') layout.separator() 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.layer_active", text=gpl.info, icon=icon).layer = i i -= 1 class GPENCIL_MT_material_active(Menu): bl_label = "Change Active Material" @classmethod def poll(cls, context): ob = context.active_object if ob is None or len(ob.material_slots) == 0: return False return True def draw(self, context): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' ob = context.active_object for slot in ob.material_slots: mat = slot.material if mat and mat.id_data and mat.id_data.preview: icon = mat.id_data.preview.icon_id layout.operator("gpencil.material_set", text=mat.name, icon_value=icon).slot = mat.name 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_fill", text="Boundary Strokes").mode = 'ACTIVE' layout.operator("gpencil.frame_clean_fill", text="Boundary Strokes all Frames").mode = 'ALL' layout.separator() 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_duplicate", text="Delete Duplicated Frames") layout.operator("gpencil.recalc_geometry", text="Recalculate Geometry") if ob.mode != 'PAINT_GPENCIL': 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, "show_in_front", text="", icon='XRAY' if gpl.show_in_front else 'FACESEL', emboss=False) 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'} def draw_header(self, context): if context.space_data.type not in {'VIEW_3D', 'TOPBAR', 'SEQUENCE_EDITOR'}: self.layout.prop(context.space_data, "show_annotation", text="") def draw(self, context): layout = self.layout layout.use_property_decorate = False is_clip_editor = context.space_data.type == 'CLIP_EDITOR' # Grease Pencil owner. gpd_owner = context.annotation_data_owner gpd = context.annotation_data # Owner selector. if is_clip_editor: col = layout.column() col.label(text="Data Source:") row = col.row() row.prop(context.space_data, "annotation_source", expand=True) # Only allow adding annotation ID if its owner exist if context.annotation_data_owner is None: row = layout.row() row.active = False row.label(text="No annotation source") return row = layout.row() row.template_ID(gpd_owner, "grease_pencil", new="gpencil.annotation_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_annotation_add", icon='ADD', text="") sub.operator("gpencil.layer_annotation_remove", icon='REMOVE', text="") gpl = context.active_annotation_layer if gpl: if len(gpd.layers) > 1: col.separator() sub = col.column(align=True) sub.operator("gpencil.layer_annotation_move", icon='TRIA_UP', text="").type = 'UP' sub.operator("gpencil.layer_annotation_move", icon='TRIA_DOWN', text="").type = 'DOWN' tool_settings = context.tool_settings if gpd and gpl: layout.prop(gpl, "annotation_opacity", text="Opacity", slider=True) 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.annotation_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.annotation_data_owner is None: return False elif type(context.annotation_data_owner) is bpy.types.Object: return False else: gpl = context.active_annotation_layer if gpl is None: return False return True def draw_header(self, context): gpl = context.active_annotation_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_annotation_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 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 if gpencil_paint else None 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_material_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.material_isolate", icon='RESTRICT_VIEW_ON', text="").affect_visibility = True sub.operator("gpencil.material_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.material_select", text="Select").deselect = False row.operator("gpencil.material_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 len(ob.material_slots) > 0 and ob.active_material_index >= 0: ma = ob.material_slots[ob.active_material_index].material else: ma = gp_settings.material else: if len(ob.material_slots) > 0 and ob.active_material_index >= 0: ma = ob.material_slots[ob.active_material_index].material if is_view3d and ma is not None and ma.grease_pencil is not None: gpcolor = ma.grease_pencil if gpcolor.stroke_style == 'SOLID': row = layout.row() row.prop(gpcolor, "color", text="Stroke Color") else: space = context.space_data row.template_ID(space, "pin_id") class GreasePencilVertexcolorPanel: def draw(self, context): layout = self.layout layout.use_property_split = True layout.use_property_decorate = False ts = context.scene.tool_settings is_vertex = context.mode == 'VERTEX_GPENCIL' gpencil_paint = ts.gpencil_vertex_paint if is_vertex else ts.gpencil_paint brush = gpencil_paint.brush gp_settings = brush.gpencil_settings tool = brush.gpencil_vertex_tool if is_vertex else brush.gpencil_tool ob = context.object if ob: col = layout.column() col.template_color_picker(brush, "color", value_slider=True) sub_row = layout.row(align=True) sub_row.prop(brush, "color", text="") sub_row.prop(brush, "secondary_color", text="") sub_row.operator("gpencil.tint_flip", icon='FILE_REFRESH', text="") row = layout.row(align=True) row.template_ID(gpencil_paint, "palette", new="palette.new") if gpencil_paint.palette: layout.template_palette(gpencil_paint, "palette", color=True) if tool in {'DRAW', 'FILL'} and is_vertex is False: row = layout.row(align=True) row.prop(gp_settings, "vertex_mode", text="Mode") row = layout.row(align=True) row.prop(gp_settings, "vertex_color_factor", slider=True, text="Mix Factor") 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) icon_mask = 'MOD_MASK' if gpl.use_mask_layer else 'LAYER_ACTIVE' row.prop(gpl, "use_mask_layer", text="", icon=icon_mask, 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.use_simplify and rd.simplify_gpencil col = layout.column() col.prop(rd, "simplify_gpencil_onplay") col.prop(rd, "simplify_gpencil_view_fill") col.prop(rd, "simplify_gpencil_modifier") col.prop(rd, "simplify_gpencil_shader_fx") col.prop(rd, "simplify_gpencil_tint") col.prop(rd, "simplify_gpencil_antialiasing") class GreasePencilLayerTransformPanel: def draw(self, context): layout = self.layout layout.use_property_split = True ob = context.object gpd = ob.data gpl = gpd.layers.active layout.active = not gpl.lock row = layout.row(align=True) row.prop(gpl, "location") row = layout.row(align=True) row.prop(gpl, "rotation") row = layout.row(align=True) row.prop(gpl, "scale") class GreasePencilLayerAdjustmentsPanel: def draw(self, context): layout = self.layout layout.use_property_split = True 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") class GPENCIL_UL_masks(UIList): def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index): mask = item if self.layout_type in {'DEFAULT', 'COMPACT'}: row = layout.row(align=True) row.prop(mask, "name", text="", emboss=False, icon_value=icon) row.prop(mask, "invert", text="", emboss=False) row.prop(mask, "hide", text="", emboss=False) elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.prop(mask, "name", text="", emboss=False, icon_value=icon) class GPENCIL_MT_layer_mask_menu(Menu): bl_label = "Layer Specials" def draw(self, context): layout = self.layout ob = context.object gpd = ob.data gpl_active = gpd.layers.active done = False for gpl in gpd.layers: if gpl != gpl_active and gpl.info not in gpl_active.mask_layers: done = True layout.operator("gpencil.layer_mask_add", text=gpl.info).name = gpl.info if done is False: layout.label(text="No layers to add") class GreasePencilLayerMasksPanel: def draw_header(self, context): ob = context.active_object gpd = ob.data gpl = gpd.layers.active self.layout.prop(gpl, "use_mask_layer", text="") def draw(self, context): ob = context.active_object gpd = ob.data gpl = gpd.layers.active layout = self.layout layout.enabled = gpl.use_mask_layer if gpl: rows = 4 row = layout.row() col = row.column() col.template_list("GPENCIL_UL_masks", "", gpl, "mask_layers", gpl.mask_layers, "active_mask_index", rows=rows, sort_lock=True) col2 = row.column(align=True) col2.menu("GPENCIL_MT_layer_mask_menu", icon='ADD', text="") col2.operator("gpencil.layer_mask_remove", icon='REMOVE', text="") col2.separator() sub = col2.column(align=True) sub.operator("gpencil.layer_mask_move", icon='TRIA_UP', text="").type = 'UP' sub.operator("gpencil.layer_mask_move", icon='TRIA_DOWN', text="").type = 'DOWN' class GreasePencilLayerRelationsPanel: def draw(self, context): layout = self.layout layout.use_property_split = True layout.use_property_decorate = False scene = context.scene 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") layout.separator() 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) # Only enable this property when a view layer is selected. col.enabled = bool(gpl.viewlayer_render) col.prop(gpl, "use_viewlayer_masks") 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 use_colors = context.preferences.edit.use_anim_channel_group_colors col = layout.column(align=True) col.active = use_colors row = col.row(align=True) row.prop(gpl, "channel_color") if not use_colors: col.label(text="Channel Colors are disabled in Animation preferences") row = layout.row(align=True) row.prop(gpl, "use_solo_mode", text="Show Only on Keyframed") class GreasePencilFlipTintColors(Operator): bl_label = "Flip Colors" bl_idname = "gpencil.tint_flip" bl_description = "Switch tint colors" @classmethod def poll(cls, context): ts = context.tool_settings settings = None if context.mode == 'PAINT_GPENCIL': settings = ts.gpencil_paint if context.mode == 'SCULPT_GPENCIL': settings = ts.gpencil_sculpt_paint elif context.mode == 'WEIGHT_GPENCIL': settings = ts.gpencil_weight_paint elif context.mode == 'VERTEX_GPENCIL': settings = ts.gpencil_vertex_paint return settings and settings.brush def execute(self, context): ts = context.tool_settings settings = None if context.mode == 'PAINT_GPENCIL': settings = ts.gpencil_paint if context.mode == 'SCULPT_GPENCIL': settings = ts.gpencil_sculpt_paint elif context.mode == 'WEIGHT_GPENCIL': settings = ts.gpencil_weight_paint elif context.mode == 'VERTEX_GPENCIL': settings = ts.gpencil_vertex_paint brush = settings.brush color = brush.color secondary_color = brush.secondary_color orig_prim = color.hsv orig_sec = secondary_color.hsv color.hsv = orig_sec secondary_color.hsv = orig_prim return {'FINISHED'} classes = ( GPENCIL_MT_snap, GPENCIL_MT_snap_pie, GPENCIL_MT_cleanup, GPENCIL_MT_move_to_layer, GPENCIL_MT_layer_active, GPENCIL_MT_material_active, GPENCIL_MT_gpencil_draw_delete, GPENCIL_MT_layer_mask_menu, GPENCIL_UL_annotation_layer, GPENCIL_UL_layer, GPENCIL_UL_masks, GreasePencilFlipTintColors, ) if __name__ == "__main__": # only for live edit. from bpy.utils import register_class for cls in classes: register_class(cls)