diff options
Diffstat (limited to 'release/scripts/startup/bl_ui/properties_grease_pencil_common.py')
-rw-r--r-- | release/scripts/startup/bl_ui/properties_grease_pencil_common.py | 456 |
1 files changed, 450 insertions, 6 deletions
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index 4789d119192..5b5a7648d83 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -19,11 +19,34 @@ # <pep8 compliant> -class GreasePencilPanel(): +from bpy.types import Menu, UIList + + +def gpencil_stroke_placement_settings(context, layout, gpd): + col = layout.column(align=True) + + col.label(text="Stroke Placement:") + + row = col.row(align=True) + row.prop_enum(gpd, "draw_mode", 'VIEW') + row.prop_enum(gpd, "draw_mode", 'CURSOR') + + if context.space_data.type == 'VIEW_3D': + row = col.row(align=True) + row.prop_enum(gpd, "draw_mode", 'SURFACE') + row.prop_enum(gpd, "draw_mode", 'STROKE') + + row = col.row(align=False) + row.active = gpd.draw_mode in {'SURFACE', 'STROKE'} + row.prop(gpd, "use_stroke_endpoints") + + +class GreasePencilDrawingToolsPanel: # subclass must set # bl_space_type = 'IMAGE_EDITOR' - # bl_region_type = 'TOOLS' bl_label = "Grease Pencil" + bl_category = "Grease Pencil" + bl_region_type = 'TOOLS' @staticmethod def draw(self, context): @@ -31,19 +54,440 @@ class GreasePencilPanel(): col = layout.column(align=True) + col.label(text="Draw:") row = col.row(align=True) row.operator("gpencil.draw", text="Draw").mode = 'DRAW' - row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT' + row.operator("gpencil.draw", text="Erase").mode = 'ERASER' row = col.row(align=True) + row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT' row.operator("gpencil.draw", text="Poly").mode = 'DRAW_POLY' - row.operator("gpencil.draw", text="Erase").mode = 'ERASER' row = col.row(align=True) - row.prop(context.tool_settings, "use_grease_pencil_sessions") + row.prop(context.tool_settings, "use_grease_pencil_sessions", text="Continuous Drawing") + + if context.space_data.type in {'VIEW_3D', 'CLIP_EDITOR'}: + col.separator() + col.label("Data Source:") + row = col.row(align=True) + if context.space_data.type == 'VIEW_3D': + row.prop(context.tool_settings, "grease_pencil_source", expand=True) + elif context.space_data.type == 'CLIP_EDITOR': + row.prop(context.space_data, "grease_pencil_source", expand=True) + + gpd = context.gpencil_data + if gpd: + col.separator() + gpencil_stroke_placement_settings(context, col, gpd) if context.space_data.type == 'VIEW_3D': col.separator() + col.separator() - col.label(text="Measure:") + col.label(text="Tools:") + col.operator("gpencil.convert", text="Convert...") col.operator("view3d.ruler") + + +class GreasePencilStrokeEditPanel: + # subclass must set + # bl_space_type = 'IMAGE_EDITOR' + bl_label = "Edit Strokes" + bl_category = "Grease Pencil" + bl_region_type = 'TOOLS' + + @classmethod + def poll(cls, context): + return (context.gpencil_data is not None) + + @staticmethod + def draw(self, context): + layout = self.layout + + gpd = context.gpencil_data + edit_ok = bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode) + + col = layout.column(align=True) + col.prop(gpd, "use_stroke_edit_mode", text="Enable Editing", icon='EDIT', toggle=True) + + col.separator() + + col.label(text="Select:") + subcol = col.column(align=True) + subcol.active = edit_ok + subcol.operator("gpencil.select_all", text="Select All") + subcol.operator("gpencil.select_border") + subcol.operator("gpencil.select_circle") + + col.separator() + + subcol = col.column(align=True) + subcol.active = edit_ok + subcol.operator("gpencil.select_linked") + subcol.operator("gpencil.select_more") + subcol.operator("gpencil.select_less") + + col.separator() + + col.label(text="Edit:") + row = col.row(align=True) + row.active = edit_ok + row.operator("gpencil.copy", text="Copy") + row.operator("gpencil.paste", text="Paste") + + subcol = col.column(align=True) + subcol.active = edit_ok + subcol.operator("gpencil.delete", text="Delete") + subcol.operator("gpencil.duplicate_move", text="Duplicate") + subcol.operator("transform.mirror", text="Mirror").gpencil_strokes = True + + col.separator() + + subcol = col.column(align=True) + subcol.active = edit_ok + subcol.operator("transform.translate").gpencil_strokes = True # icon='MAN_TRANS' + subcol.operator("transform.rotate").gpencil_strokes = True # icon='MAN_ROT' + subcol.operator("transform.resize", text="Scale").gpencil_strokes = True # icon='MAN_SCALE' + + col.separator() + + subcol = col.column(align=True) + subcol.active = edit_ok + subcol.operator("transform.bend", text="Bend").gpencil_strokes = True + subcol.operator("transform.shear", text="Shear").gpencil_strokes = True + subcol.operator("transform.tosphere", text="To Sphere").gpencil_strokes = True + + +############################### + +class GPENCIL_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_PIE_settings_palette" + + # Editing tools + if gpd: + if gpd.use_stroke_edit_mode and context.editable_gpencil_strokes: + # S - Exit Edit Mode + pie.prop(gpd, "use_stroke_edit_mode", text="Exit Edit Mode", icon='EDIT') + + # N - Transforms + col = pie.column() + row = col.row(align=True) + row.operator("transform.translate", icon='MAN_TRANS').gpencil_strokes = True + row.operator("transform.rotate", icon='MAN_ROT').gpencil_strokes = True + row.operator("transform.resize", text="Scale", icon='MAN_SCALE').gpencil_strokes = True + row = col.row(align=True) + row.label("Proportional Edit:") + row.prop(context.tool_settings, "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') + + # NE - Select (Modal) + col = pie.column() + col.operator("gpencil.select_border", text="Border 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') + + # 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_PIE_tools_more" + else: + # Toggle Edit Mode + pie.prop(gpd, "use_stroke_edit_mode", text="Enable Stroke Editing", icon='EDIT') + + +class GPENCIL_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 + + # W - Stroke draw settings + col = pie.column(align=True) + col.label(text="Stroke") + col.prop(gpl, "color", text="") + col.prop(gpl, "alpha", text="", slider=True) + + # E - Fill draw settings + col = pie.column(align=True) + col.label(text="Fill") + col.prop(gpl, "fill_color", text="") + col.prop(gpl, "fill_alpha", text="", slider=True) + + # S - Layer settings + col = pie.column() + col.prop(gpl, "line_width", slider=True) + # col.prop(gpl, "use_volumetric_strokes") + col.prop(gpl, "use_onion_skinning") + + # N - Active Layer + # XXX: this should show an operator to change the active layer instead + col = pie.column() + col.label("Active Layer: ") + col.prop(gpl, "info", text="") + # col.prop(gpd, "layers") + row = col.row() + row.prop(gpl, "lock") + row.prop(gpl, "hide") + + +class GPENCIL_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", icon='COPYDOWN', text="Copy") + col.operator("gpencil.paste", icon='PASTEDOWN', text="Paste") + + col = pie.column(align=True) + col.operator("gpencil.select_more", icon='ZOOMIN') + col.operator("gpencil.select_less", icon='ZOOMOUT') + + pie.operator("transform.mirror", icon='MOD_MIRROR').gpencil_strokes = True + pie.operator("transform.bend", icon='MOD_SIMPLEDEFORM').gpencil_strokes = True + pie.operator("transform.shear", icon='MOD_TRIANGULATE').gpencil_strokes = True + pie.operator("transform.tosphere", icon='MOD_MULTIRES').gpencil_strokes = True + + pie.operator("gpencil.convert", icon='OUTLINER_OB_CURVE', text="Convert...") + pie.operator("wm.call_menu_pie", text="Back to Main Palette...").name = "GPENCIL_PIE_tool_palette" + + +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 + + split = layout.split(percentage=0.25) + row = split.row(align=True) + row.prop(gpl, "color", text="", emboss=gpl.is_stroke_visible) + row.prop(gpl, "fill_color", text="", emboss=gpl.is_fill_visible) + split.prop(gpl, "info", text="", emboss=False) + + row = layout.row(align=True) + row.prop(gpl, "lock", text="", emboss=False) + row.prop(gpl, "hide", text="", emboss=False) + elif self.layout_type in {'GRID'}: + layout.alignment = 'CENTER' + layout.label(text="", icon_value=icon) + + +class GreasePencilDataPanel: + # subclass must set + # bl_space_type = 'IMAGE_EDITOR' + bl_label = "Grease Pencil" + bl_region_type = 'UI' + + @staticmethod + def draw_header(self, context): + self.layout.prop(context.space_data, "show_grease_pencil", text="") + + @staticmethod + def draw(self, context): + layout = self.layout + + # owner of Grease Pencil data + gpd_owner = context.gpencil_data_owner + gpd = context.gpencil_data + + # Owner Selector + if context.space_data.type == 'VIEW_3D': + layout.prop(context.tool_settings, "grease_pencil_source", expand=True) + elif context.space_data.type == 'CLIP_EDITOR': + layout.prop(context.space_data, "grease_pencil_source", expand=True) + + # Grease Pencil data selector + layout.template_ID(gpd_owner, "grease_pencil", new="gpencil.data_add", unlink="gpencil.data_unlink") + + # Grease Pencil data... + if gpd: + 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 = 2 + col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index", rows=layer_rows) + + col = row.column() + + sub = col.column(align=True) + sub.operator("gpencil.layer_add", icon='ZOOMIN', text="") + sub.operator("gpencil.layer_remove", icon='ZOOMOUT', text="") + + gpl = context.active_gpencil_layer + if gpl: + sub.operator("gpencil.layer_duplicate", icon='COPY_ID', text="") # XXX: needs a dedicated icon + + 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' + + if gpl: + self.draw_layer(layout, gpl) + + def draw_layer(self, layout, gpl): + # layer settings + split = layout.split(percentage=0.5) + split.active = not gpl.lock + + # Column 1 - Stroke + col = split.column(align=True) + col.label(text="Stroke:") + col.prop(gpl, "color", text="") + col.prop(gpl, "alpha", slider=True) + + # Column 2 - Fill + col = split.column(align=True) + col.label(text="Fill:") + col.prop(gpl, "fill_color", text="") + col.prop(gpl, "fill_alpha", text="Opacity", slider=True) + + # Options + split = layout.split(percentage=0.5) + split.active = not gpl.lock + + col = split.column(align=True) + col.prop(gpl, "line_width", slider=True) + col.prop(gpl, "use_volumetric_strokes") + + col = split.column(align=True) + col.prop(gpl, "show_x_ray") + + # if debug: + # layout.prop(gpl, "show_points") + + layout.separator() + + # Full-Row - Frame Locking (and Delete Frame) + row = layout.row(align=True) + row.active = not gpl.lock + + if gpl.active_frame: + lock_status = "Locked" if gpl.lock_frame else "Unlocked" + lock_label = "Frame: %d (%s)" % (gpl.active_frame.frame_number, lock_status) + else: + lock_label = "Lock Frame" + row.prop(gpl, "lock_frame", text=lock_label, icon='UNLOCKED') + row.operator("gpencil.active_frame_delete", text="", icon='X') + + layout.separator() + + # Onion skinning + col = layout.column(align=True) + col.active = not gpl.lock + + row = col.row() + row.prop(gpl, "use_onion_skinning") + row.prop(gpl, "use_ghost_custom_colors", text="", icon='COLOR') + + split = col.split(percentage=0.5) + split.active = gpl.use_onion_skinning + + # - Before Frames + sub = split.column(align=True) + row = sub.row(align=True) + row.active = gpl.use_ghost_custom_colors + row.prop(gpl, "before_color", text="") + sub.prop(gpl, "ghost_before_range", text="Before") + + # - After Frames + sub = split.column(align=True) + row = sub.row(align=True) + row.active = gpl.use_ghost_custom_colors + row.prop(gpl, "after_color", text="") + sub.prop(gpl, "ghost_after_range", text="After") + + +class GreasePencilToolsPanel: + # subclass must set + # bl_space_type = 'IMAGE_EDITOR' + # bl_options = {'DEFAULT_CLOSED'} + bl_label = "Grease Pencil Settings" + bl_region_type = 'UI' + + @classmethod + def poll(cls, context): + return (context.gpencil_data is not None) + + @staticmethod + def draw(self, context): + layout = self.layout + + # gpd_owner = context.gpencil_data_owner + gpd = context.gpencil_data + + layout.prop(gpd, "use_stroke_edit_mode", text="Enable Editing", icon='EDIT', toggle=True) + + layout.separator() + + layout.label("Proportional Edit:") + row = layout.row() + row.prop(context.tool_settings, "proportional_edit", text="") + row.prop(context.tool_settings, "proportional_edit_falloff", text="") + + layout.separator() + layout.separator() + + gpencil_stroke_placement_settings(context, layout, gpd) |