blender/scripts/startup/bl_ui/properties_grease_pencil_common.py
Sergey Sharybin 03806d0b67 Re-design of submodules used in blender.git
This commit implements described in the #104573.

The goal is to fix the confusion of the submodule hashes change, which are not
ideal for any of the supported git-module configuration (they are either always
visible causing confusion, or silently staged and committed, also causing
confusion).

This commit replaces submodules with a checkout of addons and addons_contrib,
covered by the .gitignore, and locale and developer tools are moved to the
main repository.

This also changes the paths:
- /release/scripts are moved to the /scripts
- /source/tools are moved to the /tools
- /release/datafiles/locale is moved to /locale

This is done to avoid conflicts when using bisect, and also allow buildbot to
automatically "recover" wgen building older or newer branches/patches.

Running `make update` will initialize the local checkout to the changed
repository configuration.

Another aspect of the change is that the make update will support Github style
of remote organization (origin remote pointing to thy fork, upstream remote
pointing to the upstream blender/blender.git).

Pull Request #104755
2023-02-21 16:39:58 +01:00

915 lines
31 KiB
Python

# 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:
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")
if brush.gpencil_tool == 'DRAW':
row = layout.row(align=True)
row.active = settings.show_brush
row.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').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.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
mat.id_data.preview_ensure()
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 Duplicate 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
col = layout.column(align=True)
if gpcolor.show_stroke and gpcolor.stroke_style == 'SOLID':
col.prop(gpcolor, "color", text="Stroke Color")
if gpcolor.show_fill and gpcolor.fill_style == 'SOLID':
col.prop(gpcolor, "fill_color", text="Fill 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)